我想计算一个给定的InputStream
的CRC3``checksum
,然后用它来得到字符串。
private long calculateChecksum(InputStream stream) throws IOException {
CRC32 crc = new CRC32();
byte[] buffer = new byte[8192];
int length;
while ((length = stream.read(buffer)) > 0) {
crc.update(buffer, 0, length);
}
return crc.getValue();
}
然后
String text = IOUtils.toString(inputStream, UTF_8);
我也试过颠倒顺序。先把它当作字符串,然后再计算校验和。但是不起作用。
我的问题是在计算校验和的时候索引到了末尾,然后没有重置。你知道在计算完校验和之后如何使用InputStream吗?
3条答案
按热度按时间ybzsozfc1#
正如其他人所说,一个流只能使用一次,但是您可以通过将
InputStream
与java.util.zip.CheckedInputStream
Package 在一起,在使用它的同时计算CRC值。下面是一个完整的示例,假设文本文件“test.txt”位于当前目录中,并且只包含以下一行:
These are german umlauts: äöüÄÖÜß
输出:
mutmk8jj2#
InputStream
是一个只读一次的流。一旦你读了它,你就不能回去重新开始。这是因为InputStream
是通用的:它可以是例如从键盘读取的字节流,或者是从实时数据馈送读取的字节流。如果输入流实际上是
FileInputStream
,则可以使用将其重置为文件的开头。
如果它是
ByteArrayInputStream
,那么你已经有了一个字节数组,所以你可以直接用它来代替。如果你想写一个通用函数,而它不知道给定的是什么类型的
InputStream
,那么你可以把它 Package 在一个BufferedInputStream
中,并使用它的mark()
方法,这将使用额外的内存来缓冲整个流。eit6fx6z3#
是的,InputStream被消耗。您有几个选项:
mark
mark()
/reset()
是输入流的可选方法;mark设置一个标记(它本身什么也不做),并重置“rewind back”到该标记,重放自上次调用mark()
以来提供的所有内容。然而,一般的输入流要么不支持它,要么支持它,将设置标记后接收到的所有字节存储在内存中,也就是说,如果你对一个包含几GB数据的输入流这样做,你将得到一个
OutOfMemoryError
。如果数据不多,就使用mark和reset, Package 一个BufferedInputStream,它支持mark/reset:
1.重复
第二种选择是复制输入流,将每个检索到的字节都发送给IOUtils和CRC算法。
这很复杂,不推荐使用。
1.改为对字符串进行校验和。
您已经有一个数据字符串。只需校验和:
或者,抛弃借据: