如何反复读取同一个 InputStream 对象

  我们知道,每次从 InputStream 对象中读取数据后,其当前读取位置的指针就会发生移动。如果在读取完的某时还想重新从此 InputStream 对象中读取数据,但此指针已到尽头,因此无法做到这一点。另外,InputStream 还不支持克隆,这意味着也不能事先备份这个 InputStream 对象。不过,这并不是没有办法。

方法 1

  如果使用的 InputStream 对象支持方法 mark,可以联合方法 reset 来进行 InputStream 对象的读取重置。方法是,先使用方法 mark 标记一个位置,然后之后在需要重置的时候,使用方法 reset 来将此 InputStream 对象重置到刚才的位置。

  方法 mark 的使用规则如下。当 InputStream 对象调用方法 mark 时,它会在此 InputStream 对象的当前读取位置做一个标记。不过,它需要提供一个参数,这个参数是一个读取范围。在标记后继续从 InputStream 中读取数据时,如果读取到的数据大小超过了这个范围,则之后调用方法 reset 时将直接抛出异常。可以看出,在此处,这个参数没有太大的作用,最好设置为大于需要读取的数据大小,一般设置为在此 InputStream 对象的方法 available 的返回值即可。

  使用模板如下:

 // 如果此 inputStream 支持方法 mark
 if (inputStream.markSupported()) {
    try {
        inputStream.mark(imageStream.available()); // 在当前位置作标记
    } catch (IOException ioException) {
        ioException.printStackTrace(); // TODO:处理异常
    }

    // TODO:从此 InputStream 对象中读取数据

    try {
        inputStream.reset(); // 将 inputStream 重置
    } catch (IOException ioException) {
        ioException.printStackTrace(); // TODO:处理异常
    }

    // TODO:重新开始从此 InputStream 对象中读取数据

    try {
        inputStream.reset(); // 将 inputStream 再次进行重置,以供以后可能进行的再次读取
    } catch (IOException ioException) {
        ioException.printStackTrace(); // TODO:处理异常
    }

} else {
    // TODO:如果不支持方法 mark,使用其它的办法
}

方法 2

  如果使用的 InputStream 对象不支持方法 mark(比如,FileInputStream 就不支持此方法),可以考虑使用经典的方法,这种方法类似于深克隆的通用方法。可以先将此 InputStream 对象转化为另一种只读的独立的数据类型,然后再用此数据类型不断生成所需的 InputStream 对象。这种方法有很多,比方说,先将 InputStream 对象转化为 byte 数组,然后创建一个 InputStream 对象来读取此 byte 数组。但是,这种方法需要在一开始就从 InputStream 中读取完全部的数据,这样就会失去 InputStream 对象惰性读取的优势,因此最好使用上面的 方法 1。这里给出借助 byte 数组来完成这一功能的办法。

byte 数组与 InputStream 的相互转化

byte 数组转 InputStream

public static byte[] inputStream2byteArray(InputStream inputStream) throws IOException {
    return inputStream.readAllBytes();
}

InputStream转 byte 数组

public static InputStream byteArray2InputStream(byte[] bytes) {
    return new ByteArrayInputStream(bytes);
}

实现反复读 InputStream

byte[] bytes = new byte[0];
try {
    bytes = inputStream2byteArray(inputStream);
} catch (IOException ioException) {
    ioException.printStackTrace(); // TODO:处理异常
}

// TODO:当需要 InputStream 时,可以直接获得一个新的 InputStream。
var needInputStream = byteArray2InputStream(bytes);

// TODO:反复获得 InputStream
var needInputStream2 = byteArray2InputStream(bytes);

// TODO:...
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值