Java java.io.filenotfoundexception for file path with cyrillic characters
Asked Answered
A

4

18

I have a file whose name contains characters not only from the plain ASCII character set, but also from a non-ASCII character set. In my case it contains Cyrillic characters.

Here's a snippet of my code:

String fileName = "/Users/dnelepov/Downloads/тест изображение.png";
File sendFile = new File(fileName);
if (sendFile.exists()) {
    // Some code
}

The code in sendFile.exists if block is not being executed.

Why isn't the file recognized?

My system configuration locale

LANG="ru_RU.UTF-8"
LC_COLLATE="ru_RU.UTF-8"
LC_CTYPE="ru_RU.UTF-8"
LC_MESSAGES="ru_RU.UTF-8"
LC_MONETARY="ru_RU.UTF-8"
LC_NUMERIC="ru_RU.UTF-8"
LC_TIME="ru_RU.UTF-8"
LC_ALL="ru_RU.UTF-8"

uname -a

Darwin Dmitrys-MacBook-Pro.local 11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:25:48 PDT 2012; root:xnu-1699.32.7~1/RELEASE_X86_64 x86_64

java -version

java version "1.7.0_21"
Java(TM) SE Runtime Environment (build 1.7.0_21-b12)
Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode)

UPDATE

I found that this error is on JDK from Oracle.

I created project on Eclipse, and file was found. I checked project properties and found Mac OS 6 JDK.

Then I change it to JDK 7 and file was not Found again.

My problem is that I need to use JDK 7 with JavaFX. Not Mac OS version. So my problem still exists.

I've made a video to show this error Video with error

UPDATE 2

Thanks to eumust for answer, this code works:

Path path = Paths.get("/Users/dnelepov/Downloads/test/");
    Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path oneF, BasicFileAttributes attrs) throws IOException {
            System.out.println("FILE:" + oneF);
            if (Files.exists(oneF)) {
                System.out.println("EXISTS:" + oneF);
            }
            return FileVisitResult.CONTINUE;
        }
    });

https://mcmap.net/q/742109/-java-on-mac-os-filenotfound-if-path-contatins-non-latin-characters

Antipas answered 6/6, 2013 at 17:19 Comment(11)
I take it this is Mac OS X?Galactometer
Yes, and it's killing me :(Antipas
I don't like these "�" symbols. Have you checked your terminal's encoding [Could it be, that the terminal in Mac OS X uses ISO 8859-5 by default? Take a look on the flowchart here: habrahabr.ru/post/147843 ]?Xanthe
Could you type "locale" in your terminal and show us it's output, please (just to be sure)?Xanthe
Update question for System configsAntipas
Add video showing problem.Antipas
Have you tried with a Path (not sure it makes a difference here): File f = Paths.get(fileName).toFile();?Canoe
File f = Paths.get(fileName).toFile(); - yes, file not found.Antipas
Have you checked that system property "file.encoding" inside JVM is the same with the different Java versions?Trifocals
Bad news for every one :( I install Mac OS Lion (10.8.4) and found what error still exists.Antipas
It's WORKS!!!! - https://mcmap.net/q/742109/-java-on-mac-os-filenotfound-if-path-contatins-non-latin-charactersAntipas
P
5

Just for kicks, this hack might work:

String fDir = "/Users/dnelepov/Downloads/";
char[] fileName = "тест изображение.png".toCharArray();
File root = new File(fDir);
File[] folder = root.listFiles();

for (File f : folder) 
    if (Array.equals(fileName, f.getName().toCharArray()) {
        //code here
          ...
    }

I don't know if it will yield any different results for you, especially since it may be just a weird encoding issue with the file name, but this could help shed some light on the situation. If the code doesn't execute, do a print on the int (ascii vals) of the charArray for all of the file names in the directory -- find the one you're looking for and see how the chars are encoded and why it's not equal.

Precancel answered 13/6, 2013 at 15:53 Comment(1)
This seems like a nice way to check that it can read the names of all the files in the directory. For each file I would output the result to the error log, and you can compare that string to the actual file name you are using, to find the differences. Then you'll be able to handle this error somehow - i'm guessing that ultimately you will be getting this file from user interaction? if not, can you just rename the file, could you get a pointer to its physical location on disk, size etc, then slurp in the contents ? or is that not possible and I'm talking out of my bottom ?Chaplin
B
2

I had the same with non-ascii chars and this helped (updated):

String fileName = "file:///Users/dnelepov/Downloads/тест изображение.png"; 
URI uri = new URI(null, null, fileName, null); 
System.out.println("TS:" + uri.getPath);
System.out.println("EX:" + new File(uri).exists());
Buchenwald answered 6/6, 2013 at 17:23 Comment(12)
String fileName = "/Users/dnelepov/Downloads/тест изображение.png"; String ts = new URI(fileName).getPath(); System.out.println("TS:" + ts); Result: Exception java.net.URISyntaxException: Illegal character in path at index 30: /Users/dnelepov/Downloads/тест изображение.pngAntipas
Try with new URI(null, null, yourPath, null) insteadGalactometer
No exception, but file still invisible for JavaAntipas
The problem is with the space, so you can either replace it with %20 or you can use the the solution of @fge. I'll update the answer too.Buchenwald
Balint Bako, no work. Here change path: String fileName = "/Users/dnelepov/Downloads/тест%20изображение.png"; String ts = new URI(null, null, fileName, null).getPath(); System.out.println("TS:" + ts);Antipas
@DmitryNelepov DO NOT use "%20" if you use the URI constructor -- it will take care of encoding for youGalactometer
I also meant use this or that, not bothBuchenwald
I dont understand, can you edit answer to complete code of:String fileName = "/Users/dnelepov/Downloads/тест%20изображение.png"; String ts = new URI(null, null, fileName, null).getPath(); System.out.println("TS:" + ts);Antipas
String fileName = "/Users/dnelepov/Downloads/тест изображение.png"; String ts = new URI(null, null, fileName, null).getPath(); System.out.println("TS:" + ts);Buchenwald
You might have to add a file:// prefix to the path, so it will be String fileName = "file:///Users/dnelepov/Downloads/тест изображение.png"; (yes, 3 slashes after the file)Buchenwald
And result: run: TS:/Users/dnelepov/Downloads/тест изображение.png EX:falseAntipas
That's odd, it's working for me with other non-ascii chars (I can't create the exact same file as in you example). I assume the file is there, isn't it?Buchenwald
E
2

The following code prints true on OSX when I am using Java 7 b21 with OSX 10.8.4. Based on your Kernel version it looks like you are using 10.7.

import java.io.File;

public class file {
    public static void main(String[] args) {
        File file = new File("/Users/jhawk28/Developer/filetest/тест изображение.txt");
        System.out.println(file.exists());
    }
}

Based on your included project, this is the output on my machine:

java -jar TestCyrilic.jar 
EX:true

It looks like it is a bug that was fixed in OSX 10.8.

Endurable answered 8/6, 2013 at 17:7 Comment(2)
OSX:Darwin Dmitrys-MacBook-Pro.local 11.4.2 Darwin Kernel Version 11.4.2: Thu Aug 23 16:25:48 PDT 2012; root:xnu-1699.32.7~1/RELEASE_X86_64 x86_64 ****************************************** Java:java version "1.7.0_21" Java(TM) SE Runtime Environment (build 1.7.0_21-b12) Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode) *************************** Locale: LANG="ru_RU.UTF-8" LC_COLLATE="ru_RU.UTF-8" LC_CTYPE="ru_RU.UTF-8" LC_MESSAGES="ru_RU.UTF-8" LC_MONETARY="ru_RU.UTF-8" LC_NUMERIC="ru_RU.UTF-8" LC_TIME="ru_RU.UTF-8" LC_ALL="ru_RU.UTF-8"Antipas
Maybe you just should use virtual machine with OS/JDK which will behave more predictable.Nonpartisan
R
2

I have replaced cyrillic characters with unicode equivalents and it seems to work for me:

String fileName = "/Users/user1/тест \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435.txt";

Give it a shot

Rood answered 9/6, 2013 at 15:12 Comment(1)
String fileName = "/Users/dnelepov/Downloads/test/\u0442\u0435\u0441\u0442\u0020\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435.png"; System.out.println("EX:" + new File(fileName).exists()); - result EX:falseAntipas

© 2022 - 2024 — McMap. All rights reserved.