我有XML文件(以UTF-8编码)有两个问题:
其中一些(并非全部)包含Byte order mark EF BB BF
其中一些(不是全部)包含Null字符00,分布在整个文件中。
这两个问题阻止我使用SAX Parser解析XML。我目前的方法是将文件读入一个字符串并使用正则表达式来提取这些字符并将字符串写回文件,这很好。 但是我的文件非常大(几百兆字节)并且将文件读入一个String并且每次调用replaceAll()时都会创建一个相同大小的字符串,很快就会导致java堆空间错误。
增加堆大小绝对不是一个长期解决方案。我需要流式传输文件并动态提取所有这些字符。
有关如何使用高效解决方案的任何建议?
答案 0 :(得分:7)
我会将FilterInputStream
子类化为在运行时过滤掉不需要的字节。
任务应该相当简单,因为字节顺序标记可能只在文件的开头(所以你只需要在那里检查),并且可以通过简单的==
比较轻松地完成nul-bytes(no需要类似正则表达式的功能。)
这很可能也会提高性能,因为在重新读取之前不需要将完整的更正文件写出到磁盘上。
答案 1 :(得分:1)
为什么不在将数据读入SAX解析器时过滤数据。这样您就不需要重写文件了。您可以覆盖FilterInputStream的read()方法以删除您不想要的字节。
我认为这就是@Joachim的建议。 ;)
答案 2 :(得分:1)
我只专注于BOM,看到空字节的问题为时已晚。如果有人只有BOM问题,我仍会将其作为附加内容发布。请关注downvotes。 :)强>
您可以使用支持InputStream
和mark()
的{{1}}读取前三个字节,读取前三个字节并重置它们是否不是BOM:
reset()
我使用InputStream in = new BufferedInputStream(
new FileInputStream(new File("xmlfile.xml")));
in.mark(3);
byte[] maybeBom = new byte[] {
(byte) in.read(), (byte) in.read(), (byte) in.read() };
if(!Arrays.equals(maybeBom, new byte[] { (byte) 0xEF, (byte) 0xBB, (byte) 0xBF })) {
in.reset();
}
因为BufferedInputStream
不支持FileInputStream
。