我有一个简单的代码来提取zip文件,它正常工作正常,但在我的测试期间我尝试了我的代码与一些zip文件(我从互联网上下载的字体,图标和模板)只是为了确保它应该提取提供的任何zip文件,但它不能使用某些zip文件,这里是重新生成此问题的最小化代码:
package com.test.mytest;
import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
public class ZipExtractTest {
public static final String ZIP_FILE = "/Users/XXXXX/Downloads/janne.zip";
public static void main(String[]args) {
unzipFile(ZIP_FILE);
unzipStream(ZIP_FILE);
}
public static void unzipFile(String zipName) {
try {
ZipFile zf = new ZipFile(zipName);
Enumeration ent = zf.entries();
while(ent.hasMoreElements()) {
System.out.println(ent.nextElement());
}
} catch(Exception e) {
System.out.println(e);
}
}
public static void unzipStream(String zipName) {
try {
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipName));
ZipEntry ze = zis.getNextEntry();
if(ze == null) {
System.out.println("unable to get first entry from zip file");
zis.close();
return;
}
while(ze != null) {
System.out.println("Entry Found: " + ze);
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
} catch(Exception e) {
System.out.println(e);
}
}
}
实际上在我的实际应用程序中,我必须通过输入流提取zip文件。在上面的代码中我试图提取“janne.zip”我从http://www.iconian.com/fonts/janne.zip下载了这个文件我能够使用任何zip工具提取它,并且令人惊讶的是通过“unzipFile(String zipName)”方法,但是使用unzipStream(String zipName)方法
ZipEntry ze = zis.getNextEntry();
返回null
任何帮助将不胜感激
答案 0 :(得分:16)
无法解答为何此特定文件无法与java.util.zip
一起使用,但如果您可以选择将java.util.zip.ZipInputStream
替换为Apache commons-compress {{1} (这应该是API兼容的)然后我刚刚在你的示例文件上测试了它,它似乎成功运行。
通常我发现commons-compress在解包由org.apache.commons.compress.archivers.zip.ZipArchiveInputStream
类本身以外的工具创建的文件时比java.util.zip
更可靠。
编辑:我在Eclipse中做了一些调试,看起来这个特定的zip文件在LOC签名之前有single segment spanning marker java.util.zip
{{1} 1}})第一个条目的本地标题。这是commons-compress knows how to handle但0x30304b50
没有 - 如果0x04034b50
看到除LOC签名以外的任何内容,则java.util.zip
将返回j.u.z.ZipInputStream
。< / p>
答案 1 :(得分:5)
滑稽!
我调试了你的代码并得到了同样的错误。我在ZipInputStream实现中找到了一个头检查,但在ZipFile实现中没有。
不要问我为什么,但是你的zip文件中的标题无效!
Your file is starting with: 50 4B 30 30 50 4B 03 04
A valid Zip File Header is: 50 4B 03 04
如果从文件中删除了第一个字节(50 4B 30 30
),则会得到一个有效的标题,您可以读取该文件!
答案 2 :(得分:0)
我遇到了同样的问题!幸运的是我能够解决它
首先我重置数据库中的blob数据然后使用java代码使用ZipInputStream压缩它。虽然我不确定,null ZipEntry问题可能是因为两件事:
1.数据库中的blob数据未正确存储(或者可能是已经压缩的数据库,某些数据库在存储时会压缩blob数据。你也可以google这个。)
2.输入/输出流也会带来麻烦,请参阅this
以下是我所做的详细说明:
1.使用EMPTY_BLOB重置数据库中的blob字段并提交更改
2.使用下面的java程序用.xls文件更新blob字段
DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver ()); // register driver
Connection conn =
DriverManager.getConnection ("jdbc:oracle:thin:@my-local-database:1521:test", "test1", "test1");
// It's faster when auto commit is off:
conn.setAutoCommit (false);
try
{
PreparedStatement pstmt = conn.prepareStatement("update content set file_content = ? where CONTENT_ID=2006");
File blob = new File("C:/Users/ankur/Desktop/Book1.xls");
FileInputStream in = new FileInputStream(blob);
pstmt.setBinaryStream(1, in);
pstmt.executeUpdate();
conn.commit();
conn.close();
System.out.println("file updated");
}
catch (SQLException e)
{
e.printStackTrace();
}
请注意,上述代码可以使用,但绝对不能证明编码标准和惯例 3.使用以下zip方法压缩数据
public byte[] zipByteArray(String primaryKey, byte[] input) throws IOException{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
ZipEntry entry = new ZipEntry(primaryKey);
entry.setSize(input.length);
zos.putNextEntry(entry);
zos.write(input);
zos.closeEntry();
zos.close();
return baos.toByteArray();
}
上面的方法采用一个字节数组,将其压缩,然后将其放入ByteArrayOutputStream中。您可以选择使用ByteArrayOutputStream本身,因为我将其转换为字节数组的一些要求。
4.然后,我使用准备好的语句
在blob字段中插入上面的字节数组
5.如果我使用下面给出的解压缩代码,它可以正常工作!
public byte[] unzipInputStream(InputStream is) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = null;
ZipInputStream zipIs = new ZipInputStream(new BufferedInputStream(is));
byteArrayOutputStream = new ByteArrayOutputStream();
ZipEntry entry = zipIs.getNextEntry();
while (entry != null) {
byte[] tmp = new byte[2048];
BufferedOutputStream bos = null;
bos = new BufferedOutputStream(byteArrayOutputStream);
int size = 0;
while ((size = zipIs.read(tmp)) != -1) {
bos.write(tmp, 0, size);
}
bos.flush();
bos.close();
entry = zipIs.getNextEntry();
}
zipIs.close();
return byteArrayOutputStream.toByteArray();
上述方法的输出是解压缩数据。