使用Java删除BOM字符

时间:2014-10-08 17:00:24

标签: java filereader byte-order-mark

我正在尝试使用FileReader读取文件并将它们写入单独的文件中 这些文件是UTF-8编码的,但不幸的是其中一些文件仍包含BOM 我试过的相关代码是:

private final String UTF8_BOM = "\uFEFF";

 private String removeUTF8BOM(String s)
    {
        if (s.startsWith(UTF8_BOM))
        {
            s=s.replace(UTF8_BOM, "");
        }
        return s;
    }

    line=removeUTF8BOM(line);

但由于某种原因,BOM未被删除。有没有其他方法可以用FileReader做到这一点?我知道应该有BOMInputStream,但我宁愿使用FileReader找到解决方案。

2 个答案:

答案 0 :(得分:4)

类FileReader是一个使用平台编码的旧实用程序类。在可能 UTF-8的Windows上。

最好与其他班级一起阅读。

作为娱乐,并澄清错误,这里是一个肮脏的黑客,适用于具有单字节编码的平台:

private final String UTF8_BOM = new String("\uFEFF".getBytes(StandardCharsets.UTF_8));

这将获得UTF-8字节,并在当前平台编码中生成一个String。

无需提及FileReader是不可移植的,只处理本地文件。

答案 1 :(得分:2)

对问题的天真解决方案:

public static void main(final String[] args)
{
    final String hasbom = "\uFEFF" + "Hello World!";
    final String nobom = hasbom.charAt(0) == '\uFEFF' ? hasbom.substring(1) : hasbom;
    System.out.println(hasbom.equals(nobom));
}

输出:

false

正确的解决方案方法:

您永远不应该使用基于File的API进行编程,而是针对InputStream/OutputStream进行编程,以便您的代码可以移植到不同的源位置。

这只是一个未经测试的示例,说明如何将此行为封装到InputStream中以使其透明。

public class BomProofInputStream extends InputStream
{
    private final InputStream is;

    public BomProofInputStream(@Nonnull final InputStream is)
    {
        this.is = is;
    }

    private boolean isFirstByte = true;

    @Override
    public int read() throws IOException
    {
        if (this.isFirstByte)
        {
            this.isFirstByte = false;
            final int b = is.read();
            if ("\uFEFF".charAt(0) != b) { return b; } 
        }
        return is.read();
    }
}

找到full fledged example进行了一些搜索: