如何在Java中解压非UTF8格式的文件

4
我有一个文件,比如test.zip。如果我使用像WinRAR这样的ZIP工具,提取(将test.zip解压缩为test.csv)很容易。但是test.csv不是UTF8格式的。我的问题是,当我使用Java解压缩它时,它无法读取此文件。
ZipFile zf = new ZipFile("C:/test.zip");

抛出的异常表示打开该文件时发生错误。在Java http://java.sun.com/developer/technicalArticles/Programming/compression/ 中没有关于数据格式的任何说明。也许整个API仅设计用于UTF8格式数据。那么,如果我需要解压非UTF8格式的数据,如何解压它?特别是包含更多空间大小(除了UTF8)的日文和中文字符。我还在http://truezip.java.net/6/tutorial.html上找到了一个API,其中提到了这个问题。但是,我没找到解决方法。是否有简单的方法来解决这个问题?特别是从JAVA规范请求传递的API。

什么样的“打开文件错误”? - Ed Staub
1
请描述您所看到的错误。另外尝试使用Winzip而不是WinRar打开文件。您的zip文件可能一开始就不是zip格式。这与UTF-8无关。 - Rajesh J Advani
5个回答

5

JDK6在java.util.zip实现中存在一个bug,它无法处理非USASCII字符。我使用Apache Commons commons-compress-1.0.jar库来修复这个问题。JDK7已经修复了java.util.zip实现。

http://docs.oracle.com/javase/7/docs/api/java/util/zip/ZipInputStream.html

import java.io.*;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.*;

public static int unzip(File inputZip, File outputFolder) throws IOException {
    int count=0;
    FileInputStream fis = null;
    ZipArchiveInputStream zis = null;
    FileOutputStream fos = null;
    try {
        byte[] buffer = new byte[8192];
        fis = new FileInputStream(inputZip);
        zis = new ZipArchiveInputStream(fis, "Cp1252", true); // this supports non-USACII names
        ArchiveEntry entry;
        while ((entry = zis.getNextEntry()) != null) {
            File file = new File(outputFolder, entry.getName());
            if (entry.isDirectory()) {
                file.mkdirs();
            } else {
                count++;
                file.getParentFile().mkdirs();
                fos = new FileOutputStream(file);
                int read;
                while ((read = zis.read(buffer,0,buffer.length)) != -1)
                    fos.write(buffer,0,read);
                fos.close();
                fos=null;
            }
        }
    } finally {
        try { zis.close(); } catch (Exception e) { }
        try { fis.close(); } catch (Exception e) { }
        try { if (fos!=null) fos.close(); } catch (Exception e) { }
    }
    return count;
}

3
不,zip文件并不仅限于UTF-8数据。Zip文件根本不会尝试解释文件内的数据,Java API也是如此。
可能存在与文件的非ASCII名称相关的问题,但文件内容本身不应该有任何问题。在您的情况下,看起来文件名只是test.zip,因此您不应遇到任何名称编码问题。
如果文件无法打开,则听起来您遇到了不同的问题。您确定文件存在于您期望的位置吗?

当我解压包含UTF-8格式的文件时,代码可以正常运行。但是,当需要解压的文件不是UTF-8格式时,代码会出现问题: ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile)); ZipEntry ze = zis.getNextEntry(); 这里的ze将为null。 - abishkar bhattarai
@abishkar:这对我来说听起来非常不可能。请展示一个简短但完整的程序,以展示问题。 - Jon Skeet

1

你可以尝试下面的代码吗?更多示例请查看这里 http://java2novice.com/java-collections-and-util/zip/unzip/

FileInputStream fis = null;
    ZipInputStream zipIs = null;
    ZipEntry zEntry = null;
    try {
        fis = new FileInputStream(filePath);
        zipIs = new ZipInputStream(new BufferedInputStream(fis));
        while((zEntry = zipIs.getNextEntry()) != null){
            try{
                byte[] tmp = new byte[4*1024];
                FileOutputStream fos = null;
                String opFilePath = "C:/"+zEntry.getName();
                System.out.println("Extracting file to "+opFilePath);
                fos = new FileOutputStream(opFilePath);
                int size = 0;
                while((size = zipIs.read(tmp)) != -1){
                    fos.write(tmp, 0 , size);
                }
                fos.flush();
                fos.close();
            } catch(Exception ex){

            }
        }
        zipIs.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

0

尝试使用我用来提取所有zip文件的代码

try
    {

        final ZipFile zf = new ZipFile("C:/Documents and Settings/satheesh/Desktop/POTL.Zip");

        final Enumeration<? extends ZipEntry> entries = zf.entries();
        ZipInputStream zipInput = null;

        while (entries.hasMoreElements())
        {
            final ZipEntry zipEntry=entries.nextElement();
            final String fileName = zipEntry.getName();
        // zipInput = new ZipInputStream(new FileInputStream(fileName));
            InputStream inputs=zf.getInputStream(zipEntry);
            //  final RandomAccessFile br = new RandomAccessFile(fileName, "r");
                BufferedReader br = new BufferedReader(new InputStreamReader(inputs, "UTF-8"));
                FileWriter fr=new FileWriter(f2);
            BufferedWriter wr=new BufferedWriter(new FileWriter(f2) );

            while((line = br.readLine()) != null)
            {
                wr.write(line);
                System.out.println(line);
                wr.newLine();
                wr.flush();
            }
            br.close();
            zipInput.closeEntry();
        }


    }
    catch(Exception e)
    {
        System.out.print(e);
    }
    finally
    {
        System.out.println("\n\n\nThe had been extracted successfully");

    }

这段代码真的以一种良好的方式为我工作。


0

据我记得,这种情况只会在文件名未以UTF8编码时发生。

如果第三方组件没有被禁用,可以尝试使用Apache Zip API。

导入org.apache.tools.zip.ZipEntry; org.apache.tools.zip.ZipFile;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接