跳转到帖子
  • 游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

    赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

    TheHackerWorld官方

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


HACK1949

推荐的帖子

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;
链接帖子
意见的链接
分享到其他网站

黑客攻防讨论组

黑客攻防讨论组

    You don't have permission to chat.
    • 最近浏览   0位会员

      • 没有会员查看此页面。
    ×
    ×
    • 创建新的...