rar4,zip壓縮文件,解壓成流的方式,再根據要求生成文件utils

rar4,zip壓縮文件,解壓成流的方式在根據要求生成文件

首先maven依賴

<!-- 導入zip解壓包(可以解決中文亂碼) -->
        <dependency>
            <groupId>ant</groupId>
            <artifactId>ant</artifactId>
            <version>1.6.5</version>
        </dependency>
        <!-- 導入rar解壓包 -->
        <dependency>
            <groupId>com.github.junrar</groupId>
            <artifactId>junrar</artifactId>
            <version>0.7</version>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-compress</artifactId>
            <version>1.8.1</version>
        </dependency>

源碼

package com.example.datasource2;


import com.github.junrar.Archive;
import com.github.junrar.rarfile.FileHeader;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.codehaus.plexus.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.io.*;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author mjp
 * <p>目前僅支持rar4,和zip文件</p>
 * @ClassName : RarUtils
 * @Date: 2019/4/3 10:41
 * @Version 1.0
 */
public class RarUtils {
    public static final String RAR_FILE = ".rar";
    public static final String ZIP_FILE = ".zip";
    /**
     * linux系統的文件分割符
     */
    public static String LINUX_SEQ = "/";
    /**
     * windows文件分割符
     */
    public static String WINDOWS_SEQ = "\\\\";




    public static Map<String, InputStream> getFileDesc(@NotNull String tempPath,String fileOriName, @NotNull MultipartFile multipartFile, String endCode) throws Exception {
        File file = multipartFileToFile(tempPath, multipartFile);
        return getFileDesc(file,fileOriName, endCode);
    }

    /**
     * <p>方法名:getFileDesc</p>
     * <p>描述: 獲取壓縮文件的所有信息</p>
     * <p>創建時間: 2019/4/8 13:56</p>
     *
     * @param file    文件(可以是原文件,但是如果被重新修改過後綴名的話,就必須要傳入源文件名)
     * @param endCode 文件編碼
     * @param fileOriName  源文件名
     * @return
     * @author mjp
     */
    public static Map<String, InputStream> getFileDesc(@NotNull File file,String  fileOriName, String endCode) throws Exception {
        if (StringUtils.isBlank(fileOriName)) {
            fileOriName = file.getName();
        }
        // rar壓縮文件
        Map<String, InputStream> resultMap;
        if (fileOriName.toLowerCase().endsWith(RAR_FILE)) {
            resultMap = readRar(file);
        } else if (fileOriName.toLowerCase().endsWith(ZIP_FILE)) {
            resultMap = readZipFile(file, endCode);
        } else {
            throw new Exception("暫不支持此壓縮文件!");
        }
        return resultMap;
    }



    /**
     * <p>描述: 文件轉換(將spring傳入的MultipartFile轉換成File)</p>
     * <p>創建時間: 2019/4/8 10:43</p>
     *
     * @param tempPath 臨時文件路徑
     * @param mf       spring文件
     * @return File 文件
     * @author mjp
     */
    public static File multipartFileToFile(String tempPath, MultipartFile mf) throws IllegalStateException, IOException {
        if (mf == null) {
            return null;
        }
        String name = mf.getName();
        File fileTemp = new File(tempPath);
        if (!fileTemp.exists()) {
            fileTemp.mkdirs();
        }
        File file = new File(fileTemp + File.separator + name);
        mf.transferTo(file);
        return file;
    }


    /**
     * <p>描述: 將spring傳輸的文件保存到臨時目錄中</p>
     * <p>創建時間: 2019/4/4 11:07</p>
     *
     * @param multipartFile 文件流
     * @param tempDir       臨時路徑
     * @return 臨時文件
     * @author mjp
     */
    public static File saveTempFile(MultipartFile multipartFile, String tempDir) throws Exception {
        if (multipartFile == null) {
            return null;
        }
        if (tempDir == null || tempDir.trim().length() == 0) {
            throw new Exception("臨時路徑不能爲空!");
        }
        //
        String fileName = multipartFile.getName();
        //臨時文件
        String tempFilePath = tempDir + File.separator + fileName;
        File tempFile = new File(tempFilePath);
        File parent = tempFile.getParentFile();
        if (!parent.exists()) {
            parent.mkdir();
        }
        boolean createResult = tempFile.createNewFile();
        if (createResult) {
            multipartFile.transferTo(tempFile);
        }
        multipartFile = null;
        return tempFile;
    }

    /**
     * <p>方法名:readZipFile</p>
     * <p>描述: 讀取壓縮文件,最後返回<p>文件路徑名,文件流</p></p>
     * <p>創建時間: 2019/4/4 11:05</p>
     *
     * @param zipFile  壓縮文件
     * @param enCoding 文件編碼方式
     * @author mjp
     */
    public static Map<String, InputStream> readZipFile(File zipFile, String enCoding) throws Exception {
        if (zipFile == null) {
            throw new Exception("文件爲空!");
        }
        // 默認編碼方式
        if (enCoding == null || enCoding.trim().length() == 0) {
            enCoding = System.getProperty("file.encoding");
        }
        ZipFile zf = new ZipFile(zipFile, enCoding);
        // 遍歷所有壓縮文件
        Map<String, InputStream> fileMap = new HashMap<String, InputStream>(16);
        for (Enumeration<ZipEntry> enumeration = zf.getEntries(); enumeration.hasMoreElements(); ) {
            ZipEntry zipEntry = enumeration.nextElement();
            String name = zipEntry.getName();
            // 由於壓縮後的文件路徑存在不確定性,統一換算成※
            name = name.replaceAll(LINUX_SEQ, "※").replaceAll(WINDOWS_SEQ, "※");
            // 解壓後文件如果是文件夾
            if (name.endsWith(WINDOWS_SEQ)) {
                continue;
            }
            // TODO(解壓的文件還是壓縮文件,該情況暫時還沒有考慮)
            InputStream in = zf.getInputStream(zipEntry);
            fileMap.put(name, in);
        }

        return fileMap;
    }

    /**
     * <p>方法名:readRar</p>
     * <p>描述: 讀取rar文件, 該方式僅只支持rar5之前的壓縮格式文件</p>
     * <p>默認返回-文件路徑--流的方式</p>
     * <p>創建時間: 2019/4/8 10:07</p>
     *
     * @param rarFile rar文件
     * @author mjp
     */
    public static Map<String, InputStream> readRar(File rarFile) throws Exception {
        FileOutputStream outputStream = null;
        InputStream in = null;
        // 文件
        String fileName = rarFile.getName();
        String pathName = null;
        Map<String, InputStream> resultMap = new HashMap<>(16);
        if (!fileName.toLowerCase().endsWith(RAR_FILE)) {
            System.err.println("非rar文件!");
            return resultMap;
        }
        Archive a = new Archive(rarFile);
        if (a.getFileHeaders().size() > 0) {
            a.getMainHeader().print();
            FileHeader fh;
            while ((fh = a.nextFileHeader()) != null) {
                // 文件夾
                if (fh.isDirectory()) {
                    // 由於此處僅僅需要文件的路徑問題, 不考慮解壓後的文件存放,所以直接跳過
                    continue;
                } else {
                    // 文件
                    if (existZH(fh.getFileNameW())) {
                        pathName = fileName.substring(0, fileName.lastIndexOf(".")) + File.separator + fh.getFileNameW().trim();
                    } else {
                        pathName = fileName.substring(0, fileName.lastIndexOf(".")) + File.separator + fh.getFileNameString().trim();
                    }
                    File tempFile = File.createTempFile(System.currentTimeMillis() + "", pathName.substring(pathName.lastIndexOf(".")));
                    outputStream = new FileOutputStream(tempFile);
                    a.extractFile(fh, outputStream);
                    in = new FileInputStream(tempFile);
                    // 爲了後期的文件名易於分割等操作
                    String replaceName = pathName.replaceAll(WINDOWS_SEQ, "※").replaceAll(LINUX_SEQ, "※");
                    resultMap.put(replaceName, in);
                }
            }
            a.close();
        }
        return resultMap;
    }


    /**
     * <p>描述: 判斷 字符串是否是中文</p>
     * <p>創建時間: 2019/4/8 8:54</p>
     *
     * @param str 字符串
     * @return boolean
     * @author mjp
     */
    public static boolean existZH(String str) {
        String zhStr = "[\\u4e00-\\u9fa5]";
        Pattern pattern = Pattern.compile(zhStr);
        Matcher matcher = pattern.matcher(str);
        if (matcher.find()) {
            return true;
        }
        return false;

    }





    /**
     * <p>方法名:generateFile</p>
     * <p>描述: 根據流生成文件</p>
     * <p>創建時間: 2019/4/8 10:55</p>
     *
     * @param savePath    文件保存路徑
     * @param fileName    文件名
     * @param inputStream 文件流
     * @return 文件存放的路徑
     * @author mjp
     */
    public static String generateFile(String savePath, String fileName, InputStream inputStream) throws IOException {
        FileOutputStream fileOutputStream = null;
        try {

            String saveName = savePath + File.separator + fileName;
            File file = new File(saveName);
            fileOutputStream = new FileOutputStream(file);
            byte[] buffer = new byte[8 * 1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, bytesRead);
            }
            return file.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

    /**
     * <p>方法名:unRar</p>
     * <p>描述: 解壓rar文件, 該方式僅只支持rar5之前的壓縮格式文件</p>
     * <p>創建時間: 2019/4/8 10:07</p>
     *
     * @param rarPath rar文件路徑
     * @param dstPath 解壓後的文件路徑
     * @author mjp
     */
    public static void unrar(String rarPath, String dstPath) throws Exception {
        if (!rarPath.toLowerCase().endsWith(RAR_FILE)) {
            System.err.println("非rar文件");
            return;
        }
        File dstDiretory = new File(dstPath);
        if (!dstDiretory.exists()) {
            dstDiretory.mkdirs();
        }
        File fol = null, out = null;
        Archive a = null;
        try {
            a = new Archive(new File(rarPath));
            if (a.getFileHeaders().size() > 0) {
                a.getMainHeader().print();
                FileHeader fh = a.nextFileHeader();
                while (fh != null) {
                    // 文件夾
                    if (fh.isDirectory()) {
                        if (existZH(fh.getFileNameW())) {
                            fol = new File(dstPath + File.separator + fh.getFileNameW());
                        } else {
                            fol = new File(dstDiretory + File.separator + fh.getFileNameString());
                        }
                        fol.mkdirs();
                    } else {
                        // 文件
                        if (existZH(fh.getFileNameW())) {
                            out = new File(dstPath + File.separator + fh.getFileNameW().trim());
                        } else {
                            out = new File(dstPath + File.separator + fh.getFileNameString().trim());
                        }
                        try {
                            if (!out.exists()) {
                                if (!out.getParentFile().exists()) {
                                    out.getParentFile().mkdirs();
                                }
                                out.createNewFile();
                            }
                            FileOutputStream os = new FileOutputStream(out);
                            a.extractFile(fh, os);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }
                    fh = a.nextFileHeader();
                }
                a.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


}

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