【问题标题】:Java regex alternative for bytes on streamJava 正则表达式替代流上的字节
【发布时间】:2011-08-18 09:38:02
【问题描述】:

我的 XML 文件(以 UTF-8 编码)有两个问题:

  • 其中一些(不是全部)包含Byte order mark EF BB BF

  • 其中一些(不是全部)包含 Null 字符 00,分布在整个文件中。

这两个问题都阻止我使用 SAX 解析器解析 XML。我目前的方法是将文件读入字符串并使用正则表达式来提取这些字符并将字符串写回文件,这很好。 但是,我的文件非常大(数百兆字节),并且每次调用 replaceAll() 时将文件读入字符串并创建相同大小的结果字符串,很快就会导致 java 堆空间错误。

增加堆大小绝对不是一个长期的解决方案。我需要流式传输文件并即时提取所有这些字符。

对高效解决方案的外观有何建议?

【问题讨论】:

    标签: java xml regex stream


    【解决方案1】:

    我会继承 FilterInputStream 以在运行时过滤掉不需要的字节。

    这个任务应该很简单,因为字节顺序标记可能只在文件的开头(所以你只需要在那里检查)并且可以通过简单的== 比较轻松地过滤 nul-bytes(不需要类似正则表达式的功能)。

    这很可能还会提高性能,因为您无需在重新读取之前将完整的更正文件写入磁盘。

    【讨论】:

    • +1 我也会这样做。如果还需要更正磁盘上的文件,可以使用相同的过滤器以合理的块从 FileInputStream 复制到 FileOutputStream(或使用来自 Apache Commons IO 的 IOUtils)。
    • 假设我正在从磁盘读取数据,您愿意继承 FilterInputStream 还是 BufferedInputStream。
    • @Will:我会扩展FilterInputStream 以增强多功能性:是否过滤是一个单独的决定,如果您扩展BufferedInputStream,您会强制使用该类的用户。他可以选择使用BufferedInputStream 进行换行的另一种方式。
    【解决方案2】:

    为什么不在将数据读入 SAX 解析器时对其进行过滤。这样你就不需要重写文件了。您可以覆盖 FilterInputStream 的 read() 方法以删除您不想要的字节。

    我认为这就是@Joachim 的建议。 ;)

    【讨论】:

      【解决方案3】:

      我只关注 BOM,发现空字节问题为时已晚。我仍然将其作为补充发布,以防有​​人仅对 BOM 有问题。请善待反对票。 :)


      您可以使用支持mark()reset()InputStream 读取前三个字节,如果它们不是 BOM,则读取前三个字节并重置:

      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 不支持mark()

      【讨论】:

        猜你喜欢
        • 2011-04-01
        • 2018-11-07
        • 2013-11-18
        • 2010-12-24
        • 2014-08-25
        • 1970-01-01
        • 2010-10-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多