JAVA壓縮zip 解決linux下中文亂碼

如果是文件目錄,則
ZipEntry zipEntry=new ZipEntry(basePath + System.getProperties().getProperty(“file.separator”));
zipEntry.setUnixMode(755);//解決linux亂碼

如果是文件,則
ZipEntry zipEntry=new ZipEntry(base);
zipEntry.setUnixMode(644);//解決linux亂碼

然後在輸出時強制設置編碼:
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(
zipFileName));
out.setEncoding(“GBK”);//解決linux亂碼


import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;

import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.ArchiveException;
import org.apache.commons.compress.archivers.ArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;


import lombok.extern.slf4j.Slf4j;

/**
 *
 * @author zhanghuikun
 */
@Slf4j
public class Zip {

    static final int BUFFER = 1024;

    public Zip() {

    }

    static {
        System.setProperty("sun.zip.encoding", System.getProperty("sun.jnu.encoding"));
    }

    private static void compress(File file, ZipOutputStream out, String basedir) {
        if (file.isDirectory()) {
            compressDirectory(file, out, basedir);
        } else {
            compressFile(file, out, basedir);
        }
    }

    /**
     * Compress a directory
     */
    private static void compressDirectory(File dir, ZipOutputStream out, String basedir) {
        if (!dir.exists()) {
            return;
        }
        File[] files = dir.listFiles();
        for (int i = 0; i < files.length; i++) {
            compress(files[i], out, basedir + dir.getName() + "/");
        }
    }

    /**
     * Compress a file
     */
    private static void compressFile(File file, ZipOutputStream out, String basedir) {

        if (!file.exists()) {
            return;
        }
        try {
            String encoding = System.getProperty("file.encoding");

            String decName = new String(file.getName().getBytes(encoding), StandardCharsets.UTF_8);
            String encName = new String(decName.getBytes(StandardCharsets.UTF_8), encoding);

            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            basedir = basedir.substring(basedir.split("/")[0].length() + 1, basedir.length());
            ZipEntry entry = new ZipEntry(basedir + encName);
            entry.setUnixMode(644);
            out.putNextEntry(entry);
            int count = -1;
            byte[] data = new byte[BUFFER];
            while ((count = bis.read(data, 0, BUFFER)) != -1) {
                out.write(data, 0, count);
            }
            bis.close();
        } catch (Exception e) {
            log.error("compressFile {} error", file.getName(), e);
        }
    }

    /**
     * * java壓縮 linux下中文文件名亂碼
     * *
     *
     * @param srcPathName
     * @param zipFileName
     */
    public static void zip(String srcPathName, String zipFileName) {

        File file = new File(srcPathName);

        File zipFile = new File(zipFileName);
        if (!file.exists()) {
            return;
        }
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(zipFile);
            CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream, new CRC32());
            ZipOutputStream out = new ZipOutputStream(cos);
            // Set the file name encoding method
            out.setEncoding(System.getProperty("sun.jnu.encoding"));
            String basedir = "";
            compress(file, out, basedir);
            out.close();
        } catch (Exception e) {
            log.error("zip {} error", srcPathName, e);
        }
    }

    /**
     * zip解壓
     * only DEFLATED entries can have EXT descriptor異常的解決方案請參考
     * https://stackoverflow.com/questions/47208272/android-zipinputstream-only-deflated-entries-can-have-ext-descriptor
     *
     * @param inputFile   待解壓文件名
     * @param destDirPath 解壓路徑
     * @param charset 編碼
     */

    public static void zipUncompress(String inputFile, String destDirPath, Charset charset) throws Exception {
        unzip(new File(inputFile), new File(destDirPath), charset.name());
    }

    public static void unzip(File zipFile, File destDir, String encoding) throws IOException, ArchiveException {
        String destDirectory = destDir.getAbsolutePath();

        try (ArchiveInputStream i = new ZipArchiveInputStream(new
                FileInputStream(zipFile), encoding, false, true)) {
            ArchiveEntry entry = null;
            while ((entry = i.getNextEntry()) != null) {
                if (!i.canReadEntryData(entry)) {
                    continue;
                }
                String name = destDirectory + File.separator + new String(entry.getName().getBytes(encoding),
                        StandardCharsets.ISO_8859_1);
                File f = new File(name);
                if (entry.isDirectory()) {
                    if (!f.isDirectory() && !f.mkdirs()) {
                        log.error("failed to create directory {}", f);
                    }
                } else {
                    File parent = f.getParentFile();
                    if (!parent.isDirectory() && !parent.mkdirs()) {
                        log.error("failed to create directory {}", parent);
                    }
                    try (OutputStream o = Files.newOutputStream(f.toPath())) {
                        IOUtils.copy(i, o);
                    }
                }
            }
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章