ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2022-11-05 20:43:12  阅读:275  来源: 互联网

标签:java 函数 学习 系统 语言 平台 方法 安装 QML c++ 数据


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,函数,学习,系统,语言,平台,方法,安装,QML,c++,数据
来源:

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有