找出i java.io.InputStream包含压缩数据的最佳方法是什么?

这是HTTP请求/响应的一部分吗?

介绍

由于所有答案都存在5年之久,因此我有责任写下来,这是怎么回事。我严重怀疑应该读取流的魔术字节!那是一个低级代码,通常应该避免。

简单的答案

miku写道:

If the Stream can be read via ZipInputStream, it should be zipped.

是的,但是在ZipInputStream的情况下,"可以读取"表示第一次调用.getNextEntry()会返回非空值。没有例外,等等。因此,您可以执行魔术字节解析,而无需执行以下操作:

boolean isZipped = new ZipInputStream(yourInputStream).getNextEntry() != null;

就是这样!

一般解压缩的想法

通常,似乎在[解压缩]时处理文件比使用流更加方便。有几个有用的库,而且ZipFile比ZipInputStream具有更多的功能。此处讨论zip文件的处理:什么是zip / unzip文件的良好Java库?因此,如果您可以使用文件,则更好!

代码样例

我需要在应用程序中仅使用流。这就是我写的用于解压缩的方法:

import org.apache.commons.io.IOUtils;

import java.util.zip.ZipEntry;

import java.util.zip.ZipInputStream;

public boolean unzip(InputStream inputStream, File outputFolder) throws IOException {

ZipInputStream zis = new ZipInputStream(inputStream);

ZipEntry entry;

boolean isEmpty = true;

while ((entry = zis.getNextEntry()) != null) {

isEmpty = false;

File newFile = new File(outputFolder, entry.getName());

if (newFile.getParentFile().mkdirs() && !entry.isDirectory()) {

FileOutputStream fos = new FileOutputStream(newFile);

IOUtils.copy(zis, fos);

IOUtils.closeQuietly(fos);

}

}

IOUtils.closeQuietly(zis);

return !isEmpty;

}

在某些情况下,ZipOutputStream未完成或未正确关闭,这意味着在将其解析为new ZipFile(f)时,结果文件将抛出IOException,因为该文件无效。即使zip文件因其他目的无效,上述操作也不会失败。

zis.getNextEntry()使InputStream前进。如果您想从InputStream重新开始,以防它不是一个zip文件,则不能这样做,因为zis.getNextEntry()使InputStream前进了。

@Luke Hm,您也许正确,您测试了吗?我是在很久以前写的,所以我不

是。我找到了一个解决方案:在将inputStream传递给ZipInputStream之前,将其包装为BufferedInputStream,这样就可以在其上调用mark()和reset()了。 stackoverflow.com/a/53047891/4265610

ZIP格式的魔术字节为50 4B。您可以测试流(使用标记和重置-您可能需要缓冲),但是我不希望这是100%可靠的方法。无法将其与以字母PK开头的US-ASCII编码文本文件区分开。

最好的方法是在打开流之前在内容格式上提供元数据,然后对其进行适当处理。

您可以检查流的前四个字节是本地文件头签名,该签名启动本地文件头,该本地文件头继续处理ZIP文件中的每个文件,如此处的规范所示为50 4B 03 04。

一点测试代码显示了它的工作原理:

byte[] buffer = new byte[4];

try {

ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("so.zip"));

ZipEntry ze = new ZipEntry("HelloWorld.txt");

zos.putNextEntry(ze);

zos.write("Hello world".getBytes());

zos.close();

FileInputStream is = new FileInputStream("so.zip");

is.read(buffer);

is.close();

}

catch(IOException e) {

e.printStackTrace();

}

for (byte b : buffer) {

System.out.printf("%H",b);

}

给我这个输出:

50 4B 3 4

我也有相同的想法(尽管在规范上值得信赖的Wikipedia-太可惜了!),但是看来这不是一种可靠的机制:"实施者应该意识到,使用或不使用此签名来标记数据描述符,都可能会遇到ZIP文件。读取ZIP文件以确保兼容性时,两种情况都应考虑在内。"

从一般角度来看,这是正确的,但我的猜测是,如果您没有签名ZipInputStream,它将因为坚持ZipEntry对象而失败。

您可以在zip文件(例如Microsoft Windows可执行文件)之前添加随机垃圾。仅当您使用中央目录而不是使用本地标头流式传输时,它们才起作用。 FWIW,Java PlugIn和WebStart使用中央目录,但现在也检查前四个字节(请参阅GIAR)。

(抱歉,GIFAR。)

不知道ZipInputStream是否会在该输入上失败。在一个智能的实现中,它将向前寻找并找到该签名。这是在自解压归档文件中完成的方式,在Windows上,无论zip条目位于何处,在文件的开头都具有PE-COFF签名,并且在文件内具有PKZIP zip条目签名。该文件既是EXE,又是ZIP。 Javas ZipInputStream会读取此流吗?我不知道,但是应该。其他实现中的ZipInputStream类(例如在DotNetZip中)可以并且将其作为zip流读取。

不是很优雅,但是很可靠:

如果可以通过ZipInputStream读取Stream,则应将其压缩。

只是看起来不太好。可能是ZIP数据流损坏了吗?

@fedearne:损坏的zip流是zip流吗?

我同意:如果ZipInputStream无法读取它,则其" meant"成为一个Zip文件并不重要。对?

这是最可靠的选择。如果它损坏了,您怎么知道它是ZIP?您只需要猜测即可。

@GvS我有已压缩的流和未压缩的流。如果可以避免,我宁愿不要尝试将损坏的zip流解析为未压缩。

如果检查4个魔术字节,则4.294.967.295(完全随机)流中的1个将为误报。你负担得起吗?损坏的流是否会以魔术字节开头的非压缩流形式更频繁地发生?

由于.zip和.xlsx都具有相同的魔术数,因此我找不到有效的zip文件(如果已重命名)。

因此,我已经使用Apache Tika查找确切的文档类型。

即使将文件类型重命名为zip,它也会找到确切的类型。

参考:https://www.baeldung.com/apache-tika

检查幻数可能不是正确的选择。

Docx文件的魔术数也相似50 4B 3 4

那是因为docx文件是zip文件。

java zip 流压缩_关于zip:检测流是否用Java压缩的最佳方法相关推荐

  1. java字节流转字符串_字节流与字符流的区别及相互转换

    先来看一下流的概念: 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输出都是以流的形 ...

  2. java多线程基础视频_【No996】2020年最新 Java多线程编程核心基础视频课程

    01.课程介绍.mp4 02.多线程编程基础-进程与线程.mp4 03.多线程编程基础-使用多线程-继承Thread类.mp4 04.多线程编程基础-使用多线程-实现Runnable接口.mp4 05 ...

  3. Java中合法的关键词_优秀程序员必须掌握的java中50个关键字

    关键字和保留字的区别 正确识别java语言的关键字(keyword)和保留字(reserved word)是十分重要的.Java的关键字对java的编译器有特殊的意义,他们用来表示一种数据类型,或者表 ...

  4. java重要基础知识点_必看 | 新人必看的Java基础知识点大梳理

    原标题:必看 | 新人必看的Java基础知识点大梳理 各位正在认真苦学Java的准大神,在这烈日炎炎的夏季里,老九君准备给大家带来一个超级大的"冰镇西瓜,"给大家清凉一下,压压惊. ...

  5. java中编码问题_[干货预警]一次搞懂Java中的编码问题

    编码问题一直是一个困扰程序员的问题,尤其是对于java程序员.因为java的跨平台特性,经常需要在多个编码之间进行转换. 下面详细讲一讲java中的编码问题 一.为什么要编码 长话短说,原因如下: 1 ...

  6. mysql数据库限流方案_用于对MySQL数据库的并发操作进行控制的方法及装置的制造方法_3...

    的数据库操作特点,预先设置的所述第一限流类型可以不同于本实施例中的设置,同样可以实现本申请的技术方案,也在本申请的保护范围之内. [0103]步骤102-3:判断MySQL数据库的threads_ru ...

  7. java中验证码发送_实现短信验证码的发送[JAVA]

    如何实现短信验证码的发送 一.基础知识补充 1.编码 2.URL 3.字节流与字符流 二.短信验证码编程实现 一.基础知识补充 1.编码 常见的编码:UTF-8 GBK Unicode GB2312 ...

  8. java channel源码_彤哥说netty系列之Java NIO核心组件之Channel

    你好,我是彤哥,本篇是netty系列的第五篇. 欢迎来我的工从号彤哥读源码系统地学习源码&架构的知识. 简介 上一章我们一起学习了如何使用Java原生NIO实现群聊系统,这章我们一起来看看Ja ...

  9. java io教学文件_通过代码实例跟我学Java语言程序设计及应用技术——Java文件IO技术及应用相关的教学示例(第3部分)...

    1.1Java文件IO技术及应用相关的教学示例(第3部分) 1.1.1文本字符流IO操作 1.字符流Reader/Writer类 提供的对字符流处理的类,它们为抽象类.其子类 (1)InputStre ...

最新文章

  1. Java NIO 学习笔记(三)----Selector
  2. php reids的geo功能,Redis GEO相关命令和功能,你造吗?
  3. Linux学习之系统编程篇:fifo
  4. java8新特性stream深入解析
  5. iOS vs. Android,应用设计该如何对症下药?
  6. 作者:周大铭,管理科学与工程博士,工业和信息化部赛迪研究院软件所助理研究员。...
  7. 第八节:实战前必须掌握的10个指令(下)
  8. 仿minecraft游戏 linux,【图片】【Codea制作仿MineCraft3D游戏】Craft Ver. 0.1发布(开源)【codea吧】_百度贴吧...
  9. 关于前端学习和笔试面试的总结
  10. CryptoJS 加解密类库的简单用法
  11. windows脚本切换网络环境
  12. html暴风粒子代码,魔兽世界课物品代码及gm指令大全(全部整理自网上).doc
  13. 使用Cmake生成跨平台项目编译解决方案
  14. Unity2D小游戏——类似QQ堂的小 demo(炸弹人)
  15. Halcon学习笔记-工业相机千兆网线和USB优劣对比
  16. mac下载、破解、安装webstorm编辑器
  17. openssl心脏滴血漏洞
  18. C#之敲击回车键触发Button的Click事件
  19. GDKOI 2016 魔卡少女
  20. 【Django】Django+Ajax下载文件(使用FileResponse)

热门文章

  1. 如何彻底搞懂面向 Web 开发者的正则表达式?
  2. 程序员的代码行数越少越好?
  3. 雷军:小米推动山寨机灭亡;苹果回应禁止第三方换电池;Javascript 引擎 V8 7.7 发布 | 极客头条...
  4. 马云:腾讯是阿里的成长伴侣;华为 2 万 CNBG 员工“投奔”余承东;18 岁学生索赔苹果 10 亿美元 | 极客头条...
  5. 华为或向苹果出售 5G 芯片;拼多多回应苹果停止供货;微信再推新功能! | 极客头条...
  6. 祸害阿里云宕机 3 小时的 IO HANG 究竟是个什么鬼?!
  7. 是谁成全了我们在吃鸡、狼人杀里的实时互动?
  8. 苹果为 macOS 重大漏洞道歉;迅雷内讧股价暴跌;小米百度在一起 | 一周业界事
  9. 关于学计算机有什么用检讨书,旷计算机课检讨书
  10. 拆箱装箱有什么作用JAVA_基础--最简单明了的拆箱装箱解释,带实例