【问题标题】:Copy the start of an InputStream复制 InputStream 的开头
【发布时间】:2011-08-21 03:03:56
【问题描述】:

我想复制 InputStream 的“开始”(即前 N 个字符),然后将流重置为其开始,以便可以重复使用。

使用 mark() 和 reset() 不适用于所有类型的输入流,所以我想知道是否有一个“通用”开源 Java 类(即流包装器)可以对任何类型执行此操作输入流。

另外,为了避免转换错误,制作副本的最安全方法是什么?

【问题讨论】:

    标签: java inputstream reset


    【解决方案1】:

    也许您可以将 InputStream 包装在 PushbackInputStream 中,这样您就可以读取前 N 个字节,然后再读取 unread() 它们以重复使用流。

    【讨论】:

    • 这只有在只想处理 PushbackInputStream 时才有用,它仅通过预缓冲来工作。
    • +1 不知道 PushbackInputStream - 很酷!我认为正确的答案。
    【解决方案2】:

    看看 apache commons IOUtils 如何复制流IOUtils#copyLarge()

    你可以这样使用populate ab ByteArrayInputStream

    • byte[] buffer = new byte[n]; // n 是从开始的大小
    • 使用IOUtils#copyLarge() 中的技术填充缓冲区
    • 使用您之前创建的 buffer 创建您的 ByteArrayInputStream

    这里是IOUtils#copyLarge()的代码sn-p

    public static long copyLarge(InputStream input, OutputStream output)
            throws IOException {
        byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
        long count = 0;
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
            count += n;
        }
        return count;
    }
    

    【讨论】:

    • 谢谢。我已经查看了来自 Commons IO 的更多源代码,但我想要的是让原始流重置为它的开始。
    • @PNS:很抱歉迟到了回复。如果不是所有 InputStream 的子类都不会覆盖默认实现,那么调用读取 n 字节数据的 reset 方法结束如何。并且默认实现抛出异常。
    • 是的,我认为 mark() 和 reset() 最接近我想要的,如果流不提供,即 markSupported() 返回 false,人们总是可以将它包装在一个BufferedInputStream 并使用它来代替。
    【解决方案3】:

    在重用流和大小无关紧要(例如几兆字节)时,获取流的byte[] 一次,然后在必要时使用存储的byte[] 重新创建ByteArrayInputStream 对象一直为我工作。 mark()reset() 不再麻烦。

    【讨论】:

    • 你的意思是,将所有流读入一个字节数组,然后重用它?不能这样做,因为我的应用程序中的输入大小可能非常大。
    【解决方案4】:

    经过相当多的实验,似乎最好的(虽然不完美)方法是使用 InputStream 的 ma​​rk()reset() 方法。

    如果原始流不支持标记/重置,一个简单的解决方法是将其包装在 BufferedInputStream 中。*

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-06
      • 2011-03-27
      • 1970-01-01
      • 2012-03-29
      • 2014-07-18
      • 2012-08-25
      • 1970-01-01
      • 2016-05-31
      相关资源
      最近更新 更多