在我的应用程序中,我试图使用Java的Inflater / Deflater类压缩/解压缩字节数组。 这是我最初使用的部分代码:
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
byte[] buffer = new byte[1024];
while (!inflater.finished()) {
int count = inflater.inflate(buffer);
outputStream.write(buffer, 0, count);
}
然后,在我部署代码之后,它将随机(非常罕见)导致整个应用程序挂起,并且当我进行线程转储时,我可以确定一个线程挂起了
at java.util.zip.Inflater.inflateBytes(Native Method)
at java.util.zip.Inflater.inflate(Inflater.java:259)
- locked java.util.zip.ZStreamRef@fc71443
at java.util.zip.Inflater.inflate(Inflater.java:280)
这种情况很少发生。然后我到处搜索,发现可能是在充气机中传递的一些空字节数据,而finished()永远不会返回true。
所以我使用了一种解决方法,而不是使用
while (!inflater.finished())
要确定是否完成,我使用了
while (inflater.getRemaining() > 0)
但是又发生了。 现在,这使我想知道导致该问题的真正原因是什么。即使在充气机中也不应该传递任何空数组,即使这样做,getRemaining()方法怎么也不会中断while循环? 有人可以帮忙吗?真的在烦我。
答案 0 :(得分:1)
由于同样的问题而困惑,我找到了此页面。
这是我的解决方法,可能会有所帮助:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
while (!inflater.finished()) {
int i = inflater.inflate(buffer);
if (i == 0) {
break;
}
byteArrayOutputStream.write(buffer, 0, i);
}
答案 1 :(得分:0)
inflate的Javadoc:
将字节解压缩到指定的缓冲区中。返回未压缩的实际字节数。返回值0表示应调用needsInput()或needsDictionary()以确定是否需要更多输入数据或预设字典。在后一种情况下,可以使用getAdler()获取所需字典的Adler-32值。
所以@Wildo Luo当然是正确的,以检查是否返回了0。
byte[] buffer = new byte[1024];
while (!inflater.finished()) {
int count = inflater.inflate(buffer);
if (count != 0 ) {
outputStream.write(buffer, 0, count);
} else {
if (inflater.needsInput()) { // Not everything read
inflater.setInput(...);
} else if (inflater.needsDictionary()) { // Dictionary to be loaded
inflater.setDictionary(...);
}
}
}
inflater.end();
我只能想象在其他地方代码不是完全正确的,也许就压缩大小而言。最好先检查一下通用代码。 Inflater(boolean nowrap)
需要一个额外的字节,即end()
调用。异常处理(最终尝试)。 Etcetera。
对于未知数据,未知事件:使用try-catch,找到压缩数据以检查它是否是基于数据的错误,并测试任何解决方案。
答案 2 :(得分:0)
遇到同样的问题...
我确信:
inflater.inflate
返回 0,输出缓冲区大小为 0。我的循环是这样的(Hive ORC 代码):
while (!(inflater.finished() || inflater.needsDictionary() ||
inflater.needsInput())) {
try {
int count = inflater.inflate(out.array(),
out.arrayOffset() + out.position(),
out.remaining());
out.position(count + out.position());
} catch (DataFormatException dfe) {
throw new IOException("Bad compression data", dfe);
}
}
当输出缓冲区被消耗完且其剩余大小为 0 后,循环将无限运行。
但我不确定是orc 还是zlib 导致的。在兽人方面,它用相同的压缩缓冲区大小填充原始数据然后进行压缩,所以理论上我不可能得到大于缓冲区大小的压缩块。可能是 zlib 或硬件。
话虽如此,当 count == 0
危险时中断循环,因为充气器中可能仍有未压缩的数据。