带有西里尔字符的文件路径的 Java java.io.filenotfoundexception

Posted

技术标签:

【中文标题】带有西里尔字符的文件路径的 Java java.io.filenotfoundexception【英文标题】:Java java.io.filenotfoundexception for file path with cyrillic characters 【发布时间】:2013-06-02 19:52:13 【问题描述】:

我有一个文件,其名称不仅包含纯 ASCII 字符集的字符,还包含非 ASCII 字符集的字符。在我的例子中,它包含西里尔字符。

这是我的代码的 sn-p:

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

sendFile.exists if 块中的代码没有被执行。

为什么文件无法识别?

我的系统配置 语言环境

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)

更新

我发现这个错误是在 Oracle 的 JDK 上。

我在 Eclipse 上创建了项目,并且找到了文件。我检查了项目属性,发现 Mac OS 6 JDK。

然后我将其更改为 JDK 7,并且再次找不到文件。

我的问题是我需要将 JDK 7 与 JavaFX 一起使用。不是 Mac OS 版本。所以我的问题依然存在。

我制作了一个视频来显示这个错误 Video with error

更新 2

感谢 eumust 的回答,此代码有效:

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://***.com/a/17481204/849961

【问题讨论】:

我认为这是 Mac OS X? 是的,我要死了:( 我不喜欢这些“�”符号。你检查过你的终端的编码[可能是,Mac OS X 中的终端默认使用 ISO 8859-5 吗?看看这里的流程图:habrahabr.ru/post/147843]? 您能否在终端中输入“locale”并向我们展示它的输出(只是为了确定)? 系统配置更新问题 【参考方案1】:

只是为了好玩,这个黑客可能会奏效:

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
          ...
    

我不知道它是否会为您带来任何不同的结果,尤其是因为它可能只是文件名的一个奇怪的编码问题,但这有助于阐明这种情况。如果代码未执行,请在 charArray 的 int (ascii vals) 上打印目录中所有文件名 - 找到您要查找的文件并查看字符的编码方式及其原因不相等。

【讨论】:

这似乎是检查它是否可以读取目录中所有文件的名称的好方法。对于每个文件,我会将结果输出到错误日志,您可以将该字符串与您正在使用的实际文件名进行比较,以找出差异。然后您将能够以某种方式处理此错误-我猜您最终将从用户交互中获取此文件?如果没有,你可以重命名文件,你能得到一个指向它在磁盘上的物理位置、大小等的指针,然后在内容中啜饮吗?或者那是不可能的,我说的是我的底线?【参考方案2】:

我对非 ascii 字符也有同样的想法,这有助于(更新):

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());

【讨论】:

String fileName = "/Users/dnelepov/Downloads/тест изображение.png";字符串 ts = new URI(fileName).getPath(); System.out.println("TS:" + ts);结果:异常 java.net.URISyntaxException:索引 30 处路径中的非法字符:/Users/dnelepov/Downloads/тест изображение.png 改用new URI(null, null, yourPath, null) 试试 没有例外,但文件对于 Java 仍然不可见 问题出在空格上,可以用%20替换,也可以使用@fge的解决方案。我也会更新答案。 巴林特巴科,没有工作。这里更改路径: String fileName = "/Users/dnelepov/Downloads/тест%20изображение.png"; String ts = new URI(null, null, fileName, null).getPath(); System.out.println("TS:" + ts);【参考方案3】:

当我在 OSX 10.8.4 上使用 Java 7 b21 时,以下代码在 OSX 上打印为 true。根据您的内核版本,您使用的是 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());
    

根据您包含的项目,这是我机器上的输出:

java -jar TestCyrilic.jar 
EX:true

看起来这是一个在 OSX 10.8 中修复的错误。

【讨论】:

OSX:Darwin Dmitrys-MacBook-Pro.local 11.4.2 达尔文内核版本 11.4.2:2012 年 8 月 23 日星期四 16:25:48 PDT;根:xnu-1699.32.7~1/RELEASE_X86_64 x86_64 *************************************** **** Java:Java 版本“1.7.0_21”Java(TM) SE 运行时环境(构建 1.7.0_21-b12)Java HotSpot(TM) 64 位服务器 VM(构建 23.21-b01,混合模式)*** ************************ 语言环境: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"跨度> 也许你应该使用带有 OS/JDK 的虚拟机,它的行为更可预测。【参考方案4】:

我已经用unicode equivalents 替换了西里尔字符,它似乎对我有用:

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

试一试

【讨论】:

字符串文件名 = "/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()); - 结果 EX:false

以上是关于带有西里尔字符的文件路径的 Java java.io.filenotfoundexception的主要内容,如果未能解决你的问题,请参考以下文章

如果路径中有西里尔字符,如何使用 require

带有 Thymeleaf 的 utf8 字符集

如何在 Java String 中将西里尔字母转换为英文拉丁文?

php 5.4 异常字符集

java I/O相关

java I/O相关