JDK 1.8.0_66, diacritics and file problems, follow up
Fabrizio Giudici
Fabrizio.Giudici at tidalwave.it
Thu May 12 12:11:25 UTC 2016
Hello.
A year ago I asked about problems with the handling of files with
diacritics in their name, as per this thread:
http://mail.openjdk.java.net/pipermail/openjfx-dev/2015-April/017183.html
For almost the whole past year I suspended the investigation and moved to
other things to do, but I've resumed the thing a few days ago, trying to
create a more controlled scenario.
Among a number of things to discuss, I think that I discovered a bug in
the JDK. I recall that I was answered that some problems are related to
the filesystem and Java can't do much, but in this case it seems there's
an inconsistency in the behaviour beetween the old IO and NIO. Consider
the test below, that given a path probes the existence and try to read
bytes by using java.io.File and java.nio.file.*:
private void tryToOpen (final Path path)
throws IOException
{
final boolean filesExists = Files.exists(path);
final boolean pathToFileExists = path.toFile().exists();
boolean canBeOpenedNio = false;
try
{
Files.readAllBytes(path);
canBeOpenedNio = true;
}
catch (IOException e)
{
}
boolean canBeOpenedIo = false;
try (final InputStream is = new FileInputStream(path.toFile()))
{
is.read();
canBeOpenedIo = true;
}
catch (IOException e)
{
}
final String result =
String.format("Files.exists(): %s, toFile.exists(): %s,
canBeOpened NIO: %s canBeOpened IO: %s ",
filesExists, pathToFileExists, canBeOpenedNio,
canBeOpenedIo)
+ toDebugString(path.toString());
assertThat(result + toDebugString(path.toString()), filesExists,
is(true));
assertThat(result + toDebugString(path.toString()),
pathToFileExists, is(true));
assertThat(result + toDebugString(path.toString()), canBeOpenedIo,
is(true));
assertThat(result + toDebugString(path.toString()),
canBeOpenedNio, is(true));
}
The Paths submitted to the test are discovered by Files.walk().
What I'm seeing is that all the troubled files show now no access problems
with NIO, while IO fails (e.g. toFile().exists() returns false while
Files.exists(path) returns true).
Message: Files.exists(): true, toFile.exists(): false, canBeOpened NIO:
true canBeOpened IO: false
/var/test-sets/MusicTestSets/iTunes-fg-20160504-1-iconv/Music/Ivo
Pogorelich/Ravel_ Gaspard De La Nuit; Prokofiev_ Piano Sonata #6/03 Ravel_
Gaspard De La Nuit - Scarbo_
Mod??r??.mp3/var/test-sets/MusicTestSets/iTunes-fg-20160504-1-iconv/Music/Ivo
Pogorelich/Ravel_ Gaspard De La Nuit; Prokofiev_ Piano Sonata #6/03 Ravel_
Gaspard De La Nuit - Scarbo_ Mod??r??.mp3 Expected: is <true> but: was
<false>
Message: Files.exists(): true, toFile.exists(): false, canBeOpened NIO:
true canBeOpened IO: false
/var/test-sets/MusicTestSets/iTunes-fg-20160504-1-noiconv/Music/Ivo
Pogorelich/Ravel_ Gaspard De La Nuit; Prokofiev_ Piano Sonata #6/03 Ravel_
Gaspard De La Nuit - Scarbo_
Mode??re??.mp3/var/test-sets/MusicTestSets/iTunes-fg-20160504-1-noiconv/Music/Ivo
Pogorelich/Ravel_ Gaspard De La Nuit; Prokofiev_ Piano Sonata #6/03 Ravel_
Gaspard De La Nuit - Scarbo_ Mode??re??.mp3 Expected: is <true> but: was
<false>
The following code thus can be used to probe a troubled Path (so far I see
that the problem only happens with the EXT4 filesytem; no problems with
e.g. BTRFS and HFS+):
private static boolean isTroubled (final @Nonnull Path path)
{
return Files.exists(path) != path.toFile().exists();
}
I was able to implement a first workaround for libraries I'm using that
unfortunately are based on java.io.File: I create a temporary symbolic
link without diacritics, use it in place of the original, then delete it
after the processing, and it works.
There are other remaining troubles with file names, but I'd like to first
have a feedback on this point.
Thanks.
--
Fabrizio Giudici - Java Architect @ Tidalwave s.a.s.
"We make Java work. Everywhere."
http://tidalwave.it/fabrizio/blog - fabrizio.giudici at tidalwave.it
More information about the core-libs-dev
mailing list