java 如何使用UTF-8编码打开java程序生成的zip文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6263141/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:05:29  来源:igfitidea点击:

how to open java program generated zip file using UTF-8 encoding

javaencodingzipunzip7zip

提问by Ben Xu

Our product has an export function, which uses ZipOutputStreamto zip a directory; however, when you try to zip a directory that contains file names with Chinese or Japanese character the export doesn't work properly. For some reason the new files in the zipped file are named differently. Here is an example of our zipping code:

我们的产品具有导出功能,ZipOutputStream用于压缩目录;但是,当您尝试压缩包含带有中文或日文字符的文件名的目录时,导出无法正常工作。出于某种原因,压缩文件中的新文件命名不同。这是我们的邮政编码示例:

ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
out.setEncoding("UTF-8");
//program to add directory to zip 
//program add/create file to zip
out.close();

My import algorithm, also built in Java, can import the zipped file correctly, even if it contains Chinese/Japanese characters in file/directory names.

我的导入算法也是用 Java 构建的,即使它在文件/目录名称中包含中文/日文字符,也可以正确导入压缩文件。

 Zipfile zipfile = new ZipFile(zipPath, "UTF-8");
 Enumeration e = zipFile.getEntries();
 while (e.hasMoreElements()) {
 entry = (ZipEntry) e.nextElement();
 String name = entry.getName();
         ....

Is the zip software's program having trouble unzipping the UTF-8 encoded files, or is there something special needed to create a zip file that can be easily used by existing software using utf-8 encoding??

zip 软件的程序是否在解压 UTF-8 编码文件时遇到问题,或者是否需要特殊的东西来创建一个 zip 文件,该文件可以被使用 utf-8 编码的现有软件轻松使用?



I have written an example program:

我写了一个示例程序:

package ZipFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;

public class ZipFolder{
public static void main(String[] a) throws Exception
{
String srcFolder = "D:/9.4_work/openscript_repo/中文124.All/中文";
String destZipFile = "D:/Eclipse_Projects/OpenScriptDebuggingProject/src/ZipFile/demo.zip";
zipFolder(srcFolder, destZipFile);
}

static public void zipFolder(String srcFolder, String destZipFile) throws Exception
{
    ZipOutputStream zip = null;
    FileOutputStream fileWriter = null;

    fileWriter = new FileOutputStream(destZipFile);
    zip = new ZipOutputStream(fileWriter);
    zip.setEncoding("UTF-8");
    // using GBK encoding, the chinese name can be correctly displayed when unzip
    // zip.setEncoding("GBK");

    addFolderToZip("", srcFolder, zip);
    zip.flush();
    zip.close();
}

static private void addFileToZip(String path, String srcFile, ZipOutputStream zip) throws Exception
{

    File folder = new File(srcFile);
    if (folder.isDirectory()) {
        addFolderToZip(path, srcFile, zip);
    }
    else {
        byte[] buf = new byte[1024];
        int len;
        FileInputStream in = new FileInputStream(srcFile);
        zip.putNextEntry(new ZipEntry(path + "/" + folder.getName()));
        while ((len = in.read(buf)) > 0) {
            zip.write(buf, 0, len);
        }
    }
}

static private void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) throws Exception
{
    File folder = new File(srcFolder);

    for (String fileName : folder.list()) {
        if (path.equals("")) {
            addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip);
        }
        else {
            addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip);
        }
    }
}

}

}

采纳答案by Nick

The top answer here may answer your question; unfortunately it seems to suggest that the Zip format doesn't really allow for creating a Zip file that will display filenames properly on any computer:

这里的最佳答案可能会回答您的问题;不幸的是,它似乎表明 Zip 格式并不能真正允许创建一个可以在任何计算机上正确显示文件名的 Zip 文件:

https://superuser.com/questions/60379/linux-zip-tgz-filenames-encoding-problem

https://superuser.com/questions/60379/linux-zip-tgz-filenames-encoding-problem

I expect it works when you set encoding to GBK, because that is your system's default encoding and so 7zip is using that for all zip files it opens.

我希望当您将编码设置为 GBK 时它会起作用,因为这是您系统的默认编码,因此 7zip 将它用于打开的所有 zip 文件。

It suggests that rarand 7zformats have better support.

它表明rar7z格式有更好的支持。

I found a blog entry specifically about UTF-8 in zips with Java. It suggests there's a newer version of the ZIP specification which the current versions of Java may not be creating, but Java 7 will do. I don't know if the Apache classes use this too.

我在 zips with Java 中找到了一个专门关于 UTF-8 的博客条目。它表明有一个较新版本的 ZIP 规范,当前版本的 Java 可能不会创建,但 Java 7 会创建。我不知道 Apache 类是否也使用它。

http://blogs.oracle.com/xuemingshen/entry/non_utf_8_encoding_in

http://blogs.oracle.com/xuemingshen/entry/non_utf_8_encoding_in

回答by sathish

The following utility class allows you to compress and decompress strings using the GZIP compression algorithm. This can be useful if you want to save long strings in a database for example.

以下实用程序类允许您使用 GZIP 压缩算法压缩和解压缩字符串。例如,如果您想在数据库中保存长字符串,这会很有用。

import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.GZIPInputStream;


public class GzipStringUtil {


    public static byte[] compressString(String uncompressedString) throws IllegalArgumentException, IllegalStateException {
        if (uncompressedString == null) {
            throw new IllegalArgumentException("The uncompressed string specified was null.");
        }
        try {
            byte[] utfEncodedBytes = uncompressedString.getBytes("UTF-8");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            GZIPOutputStream gzipOutputStream = new GZIPOutputStream(baos);
            gzipOutputStream.write(utfEncodedBytes);
            gzipOutputStream.finish();
            gzipOutputStream.close();
            return baos.toByteArray();
        }
        catch (Exception e) {
            throw new IllegalStateException("GZIP compression failed: " + e, e);
        }
    }


    public static String uncompressString(byte[] compressedString) throws IllegalArgumentException, IllegalStateException {
        if (compressedString == null) {
            throw new IllegalArgumentException("The compressed string specified was null.");
        }
        try {
            ByteArrayInputStream bais = new ByteArrayInputStream(compressedString);
            GZIPInputStream gzipInputStream = new GZIPInputStream(bais);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            for (int value = 0; value != -1;) {
                value = gzipInputStream.read();
                if (value != -1) {
                    baos.write(value);
                }
            }
            gzipInputStream.close();
            baos.close();
            return new String(baos.toByteArray(), "UTF-8");
        }
        catch (Exception e) {
            throw new IllegalStateException("GZIP uncompression failed: " + e, e);
        }
    }
}

Here is a TestCase which provides example use of the class above:

这是一个 TestCase,它提供了上述类的示例使用:

public class GzipStringUtilTest extends TestCase {

    public void testGzipStringUtil() {
        String input = "This is a test. This is a test. This is a test. This is a test. This is a test.";
        System.out.println("Input:        [" + input + "]");
        byte[] compressed = GzipStringUtil.compressString(input);
        System.out.println("Compressed:   " + Arrays.toString(compressed));
        System.out.println("-> Compressed input string of length " + input.length() + " to " + compressed.length + " bytes");
        String uncompressed = GzipStringUtil.uncompressString(compressed);
        System.out.println("Uncompressed: [" + uncompressed + "]");
        assertEquals("The uncompressed string [" + uncompressed + "] unexpectedly does not match the input string [" + input + "]", input, uncompressed);
        System.out.println("The input was compressed and uncompressed successfully, and the input matches uncompressed output.");
    }
}