读取文件时找不到零宽度无间隔

Posted

技术标签:

【中文标题】读取文件时找不到零宽度无间隔【英文标题】:Cannot find ZERO WIDTH NO-BREAK SPACE when reading file 【发布时间】:2014-10-16 14:50:49 【问题描述】:

我在尝试解析从文件中获取的 JSON 字符串时遇到了问题。我的问题是零宽度不间断空格字符(unicode 0xfeff)在我读入时位于字符串的开头,我无法摆脱它。我不想使用正则表达式,因为可能存在其他具有不同 unicode 的隐藏字符。

这是我所拥有的:

StringBuilder content = new StringBuilder();
    try 
        BufferedReader br = new BufferedReader(new FileReader("src/test/resources/getStuff.json"));
        String currentLine;
        while((currentLine = br.readLine()) != null) 
            content.append(currentLine);
        
        br.close();
     catch(Exception e) 
        Assert.fail();
    

这是 JSON 文件的开头(复制粘贴整个文件太长了,但我已经确认它是有效的):

"result":"data":"request":"year":null,"timestamp":1413398641246,...

这是我迄今为止尝试过的:

将 JSON 文件复制到 notepad++ 并显示所有字符 将文件复制到 notepad++ 并转换为不带 BOM 和 ISO 8859-1 的 UFT-8 在 sublime 等其他文本编辑器中打开 JSON 文件并保存为 UFT-8 将 JSON 文件复制到 txt 文件中并读入 尝试使用 Scanner 而不是 BufferedReader 在 intellij 中,我尝试了查看 -> 活动编辑器 -> 显示空格

如何在字符串开头没有零宽度不间断空格字符的情况下读取此文件?

【问题讨论】:

【参考方案1】:

0xEF 0xBB 0xBF 是 UTF-8 BOM,0xFE 0xFF 是 UTF-16BE BOM,0xFF 0xFE 是 UTF-16LE BOM。如果 0xFEFF 存在于字符串的前面,则意味着您创建了一个带有 BOM 的 UTF 编码文本文件。 UTF-16 BOM 可能按原样显示为 0xFEFF,而 UTF-8 BOM 仅在 BOM 本身从 UTF-8 解码为 UTF-16 时才会显示为 0xFEFF(这意味着阅读器检测到 BOM但没有跳过它)。事实上,众所周知,Java 不处理 UTF-8 BOM(请参阅错误 JDK-4508058 和 JDK-6378911)。

如果您阅读FileReader documentation,它会说:

此类的构造函数假定默认字符编码和默认字节缓冲区大小是适当的。要自己指定这些值,请在 FileInputStream 上构造一个 InputStreamReader。

您需要使用能够识别字符集的阅读器来读取文件内容,最好是能够为您读取 BOM 并根据需要在内部进行自我调整的阅读器。但更糟糕的情况是,您可以自己打开文件,读取前几个字节以检测是否存在 BOM,然后使用适当的字符集构建读取器来读取文件的其余部分。下面是一个使用 org.apache.commons.io.input.BOMInputStream 的示例,正​​是这样做的:

(来自https://***.com/a/13988345/65863)

String defaultEncoding = "UTF-8";
InputStream inputStream = new FileInputStream(someFileWithPossibleUtf8Bom);
try 
    BOMInputStream bOMInputStream = new BOMInputStream(inputStream);
    ByteOrderMark bom = bOMInputStream.getBOM();
    String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();
    InputStreamReader reader = new InputStreamReader(new BufferedInputStream(bOMInputStream), charsetName);
    //use reader
 finally 
    inputStream.close();

【讨论】:

太棒了,成功了。只是为了澄清一些事情,如果其他人读到这个。 BomInputStream 的创建是删除 bom 的原因,您可以找到有关 here 的更多信息

以上是关于读取文件时找不到零宽度无间隔的主要内容,如果未能解决你的问题,请参考以下文章

保存并读取图像,但打开文件夹时找不到

Java通过Eclipse运行时找不到文件

(Qt 5.6) 程序在切换到“发布”模式时找不到 .txt 文件

如何从数据文件中读取指定间隔的行?

JAVA零配置读取配置文件

自己编译的Python找不到numpy怎么办