Java教程

Java多线程写zip文档碰到的错误writebeyondendofstream!

本文主要是介绍Java多线程写zip文档碰到的错误writebeyondendofstream!,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Java多线程写zip文档碰到的错误writebeyondendofstream!

近期在写一个大量小文件直接压缩到一个zip的需求,因为zip中的entry每一个都是独立的,不需要增加写入,也就是一个entry文件,写一个内容,
因此直接用了多线程去处理,结果就翻车了,代码给出了如下的错误:writebeyondendofstream!
下面直接还原当时的代码情景:
复制代码
1publicclassMultiThreadWriteZipFile{
2
3privatestaticExecutorServiceexecutorService=Executors.newFixedThreadPool(50);
4
5privatestaticCountDownLatchcountDownLatch=newCountDownLatch(50);
6
7
8@Test
9publicvoidmultiThreadWriteZip()throwsIOException,InterruptedException{
10Filefile=newFile("D:\\Gis开发\\数据\\影像数据\\china_tms\\2\\6\\2.jpeg");
11//建立一个zip
12ZipOutputStreamzipOutputStream=
13newZipOutputStream(newFileOutputStream(newFile("E:\\java\\test\\test.zip")));
14
15for(inti=0;i<50;i++){
16StringentryName=i+File.separator+i+File.separator+i+".jpeg";
17executorService.submit(()->{
18try{
19writeSource2ZipFile(newFileInputStream(file),entryName,zipOutputStream);
20countDownLatch.countDown();
21}catch(IOExceptione){
22e.getLocalizedMessage();
23}
24});
25}
26//堵塞主线程
27countDownLatch.await();
28//关掉流
29zipOutputStream.close();
30}
31
32
33publicvoidwriteSource2ZipFile(InputStreaminputStream,
34StringzipEntryName,
35ZipOutputStreamzipOutputStream)throwsIOException{
36//新建entry
37zipOutputStream.putNextEntry(newZipEntry(zipEntryName));
38byte[]buf=newbyte[1024];
39intposition;
40//entry中写数据
41while((position=inputStream.read(buf))!=-1){
42zipOutputStream.write(buf);
43}
44zipOutputStream.closeEntry();
45zipOutputStream.flush();
46}
47}
复制代码
直接运行上边的代码便会报错:writebeyondendofstream
将privatestaticExecutorServiceexecutorService=Executors.newFixedThreadPool(50);
修改为
privatestaticExecutorSercviceexecutorService=Executors.newSingleThreadExecutor();
这时代码运行正常!
至于原因嘛,我们追踪下代码也就明白其中的原因了,我们先来看报错的代码出处:
在java.util包下的DeflaterOutputStream的201行(jdk1.8,其它版本可能会有差别),我们来看代码
复制代码
publicvoidwrite(byte[]b,intoff,intlen)throwsIOException{
if(def.finished()){
thrownewIOException("writebeyondendofstream");
}
if((off|len|(off+len)|(b.length-(off+len)))<0){
thrownewIndexOutOzfBoundsException();
}elseif(len==0){
return;
}
if(!def.finished()){
def.setInput(b,off,len);
while(!def.needsInput()){
deflate();
}
}
}
复制代码
关键的原因就是def.finished()对应的状态信息,而这个状态是在Deflater这个类中定义的,这个类也是Java基于ZLIB压缩库达到的,一个压缩工具类。
而下面的这段代码便是改变这个状态的,
publicvoidfinish(){
synchronized(zsRef){
finish=true;
}
}
而这个代码的调用之处,最根源是我们上边的zipOutputStream.putNextEntry(newZipEntry(zipEntryName));这行代码,
其实先思路,便是每次新增一个entry的时候,都要将上一次的entry关掉掉,这时也就触发了这个条件,而这个状态并不是进程私有的,我们通过下边的代码就可以知道
复制代码
public
classDeflater{
privatefinalZStreamRefzsRef;
privatebyte[]buf=newbyte[0];
privateintoff,len;
privateintlevel,strategy;
privatebooleansetParams;
privatebooleanfinish,finished;
privatelongbytesRead;
privatelongbytesWritten;
这篇关于Java多线程写zip文档碰到的错误writebeyondendofstream!的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!