【问题标题】:Efficient ByteArrayInputStream manipulation高效的 ByteArrayInputStream 操作
【发布时间】:2012-03-15 19:32:06
【问题描述】:

我正在处理一个ByteArrayInputStream,它包含一个由一个元素组成的 XML 文档,其中一个元素的内容是一个大的 base 64 编码字符串。我需要删除周围的标签,以便我可以解码文本并将其输出为 pdf 文档。

最有效的方法是什么?

我的下意识反应是将流读入byte数组,找到开始标记的结尾,找到结束标记的开头,然后将中间部分复制到另一个byte数组中;但这似乎效率很低,而且我正在使用的文本有时会很大(128KB)。我想要一种不需要额外的 byte 数组的方法。

【问题讨论】:

  • 谁来创建ByteArrayInputStream?你能把它变成你自己类型的实例吗?

标签: java bytearray bytearrayinputstream


【解决方案1】:

Base 64 不使用字符 <>,因此我假设您使用的是网络安全的 base64 变体,这意味着您无需担心内容中的 HTML 实体或 cmets。 如果您确实确定内容具有这种形式,请执行以下操作:

  1. 从右侧扫描以查找'<'。这将是结束标记的开始。
  2. 从该位置向左扫描,寻找'>'。这将是开始标记的结尾。

base 64 内容在这两个位置之间,排他性的。

您可以使用预置第二个数组的大小

((end - start + 3) / 4) * 3

作为解码内容长度的上限,然后 b64decode 进去。这是因为每 4 个 base64 数字编码 3 个字节。

如果您想变得更花哨,因为您知道数组的前几个字节包含可忽略的标记数据并且编码数据小于输入,您可以破坏性地解码当前字节缓冲区中的数据。

【讨论】:

    【解决方案2】:

    在阅读流的同时进行搜索和转换。

    // find the start tag
    byte[] startTag = new byte[]{'<', 't', 'a', 'g', '>'};
    int fnd = 0;
    int tmp = 0;
    while((tmp = stream.read()) != -1) {
     if(tmp == startTag[fnd]) 
      fnd++;
     else
      fnd=0;
     if(fnd == startTage.size()) break;
    }
    
    // get base64 bytes
    while(true) {
     int a = stream.read();
     int b = stream.read();
     int c = stream.read();
     int d = stream.read();
     byte o1,o2,o3; // output bytes
     if(a == -1 || a == '<') break;
     //
     ...
     outputStream.write(o1);
     outputStream.write(o2);
     outputStream.write(o3);
    }
    

    注意以上是我的浏览器写的,可能存在语法错误。

    【讨论】:

    • 那么我会使用 base64 来解码每组 4 个字节吗?能够直接写入输出流会很好。我想知道这是否会对性能产生任何影响?
    猜你喜欢
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 2011-04-07
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2019-04-16
    相关资源
    最近更新 更多