天天看點

利用Java的I/O流實作圖檔的壓縮以及解壓

檔案壓縮:
public class TestMerge {

    public static void merge(String srcFiles, String destFilePath) {
    	//判斷原檔案路徑是否為空
        if (srcFiles == null) {
            throw new IllegalArgumentException(srcFiles + " must be not null");
        }
        //建立目标檔案夾,并且判斷目标檔案夾是否存在
        File destFile = new File(destFilePath);
        if (!destFile.exists()) {
            boolean effect = destFile.mkdirs();
            if (!effect) {
                throw new IllegalArgumentException(destFile + " create failed");
            }
        }
        //擷取原檔案夾中所有的檔案
        File[] files = listAllFiles(srcFiles);
        for (File src : files) {
			//如果檔案格式不是jpg或者png,就不參與檔案合并
            if (!src.getName().endsWith("jpg") && !src.getName().endsWith("png")) {
                continue;
            }
            //記錄每個參與合并的檔案的位元組長度
            int length = (int) src.length();
			//進行檔案傳入和目的檔案的傳出
            try (FileInputStream in = new FileInputStream(src);
                 FileOutputStream out = new FileOutputStream(new File(destFile, "mergeP2.jpg"), true)) {
                //将每個參與合并的圖檔檔案的長度加在檔案位元組前,用于記錄參與合并的檔案長度,并且在解壓檔案時起到訓示此檔案解壓完成的作用
                //這裡需要将檔案的長度轉換成byte數組,再傳入目的檔案中
                //length -> byte[]   82(int) -> 32(bit)
                for (int i = 0; i < trans(length).length; i++) {
//                    System.out.println(trans(length)[i]);
                    out.write(trans(length)[i]);
                }
                //讀取原檔案中的位元組内容
                byte[] buff = new byte[1024];
                int len = -1;
                while ((len = in.read(buff)) != -1) {
                    out.write(buff, 0, len);
                }
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

	//實作int類型轉換為byte數組
    public static byte[] trans(int data) {
        //int轉換成byte[] 不需要 & 0xFF
        //0xFF是字面量:00000000 00000000 00000000 11111111
        byte[] ret = new byte[4];
        ret[0] = (byte) (data >> 24);
        ret[1] = (byte) (data >> 16);
        ret[2] = (byte) (data >> 8);
        ret[3] = (byte) data;
        return ret;
    }

	//實作byte數組轉換成int類型
    public static int byteArrayToInt(byte[] buff) {
        //byte[] 轉換成int 必須 & 0xFF
        int values = 0;
        for (int i = 0; i < 4; i++) {
            int shift = (3 - i) * 8;
            values += (buff[i] & 0xFF) << shift;
        }
        return values;
    }

	//用來顯示原檔案夾下所有的檔案,簡化添加圖檔檔案的步驟
    public static File[] listAllFiles(String srcFilePath) {
        File srcFile = new File(srcFilePath);
        if (srcFile.isFile()) {
            return new File[]{srcFile};
        }
        return srcFile.listFiles();
    }

	//測試
    public static void main(String[] args) {
//        String[] srcFiles = {"D:" + File.separator + "TestCode" + File.separator + "iotest" + File.separator + "data-a.txt",
//                "D:" + File.separator + "TestCode" + File.separator + "iotest" + File.separator + "data-b.txt",
//                "D:" + File.separator + "TestCode" + File.separator + "iotest" + File.separator + "data-c.txt"};
//        String destFilePath = "D:" + File.separator + "TestCode" + File.separator + "iotest" + File.separator + "data.txt";
//        merge(srcFiles, destFilePath);

        String srcFiles = "D:" + File.separator + "TestCode" + File.separator + "iotest" + File.separator + "spiltP";
        String destFilePath = "D:" + File.separator + "TestCode" + File.separator + "iotest" + File.separator + "mergePicture";
        long start = System.currentTimeMillis();
        merge(srcFiles, destFilePath);
        long end = System.currentTimeMillis();
        System.out.println(end-start);

    }
}

           
檔案解壓:
public class TestSplit {
    public static void splitFile(String srcFilePath, String destFilesPath) {
    	//判斷原檔案路徑是否存在
        if (srcFilePath.isEmpty()) {
            throw new IllegalArgumentException(srcFilePath + "must be not null");
        }
        
        //建立原檔案
        File srcFile = new File(srcFilePath);
        	//count用來記錄解壓得到的檔案個數,并用于檔案命名
            int count = 1;
            //建立目的檔案夾
            File destFile = new File(destFilesPath);
            //判斷目的檔案夾是否存在
            if (!destFile.exists()) {
                destFile.mkdirs();
            }
            //進行檔案傳輸
            try (FileInputStream in = new FileInputStream(srcFile)) {
                while (true) {
                	//首先讀取壓縮檔案中的前4個位元組,這4個位元組記錄了第一個解壓出的檔案長度
                    byte[] data = new byte[4];
                    int length = in.read(data);
                    if (length != 4) {
                        break;
                    }
                    //建立解壓出的檔案
                    FileOutputStream out = new FileOutputStream(new File(destFile, "p" + (count++) + ".jpg"));
                    //将壓縮檔案中的前四個位元組記錄的值轉換成int類型的檔案長度值
                    int fileLen = TestMerge.byteArrayToInt(data);
                    int len = -1;
                    //建立byte數組,數組長度為檔案長度值
                    byte[] buff = new byte[fileLen];
                    len = in.read(buff);
                    //判斷檔案是否讀取完
                    if (len != -1 && len == buff.length) {
                        //buff -> file
                        out.write(buff, 0, len);
                        out.flush();
                        out.close();
                        continue;
                    }
                    if (len == -1) {
                        break;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

	//測試
    public static void main(String[] args) {
        String directory = "D:" + File.separator + "TestCode" + File.separator + "iotest" + File.separator;
        String srcFilePath = directory + "mergePicture"+File.separator+"mergeP2.jpg";
        String destFilesPath = directory + "b";
        long start = System.currentTimeMillis();
        splitFile(srcFilePath, destFilesPath);
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }
}
           

運作結果:

測試用例中,合并了87個檔案圖檔,總共大小為328389KB,測試結果如圖:

壓縮結果以及壓縮時間:

利用Java的I/O流實作圖檔的壓縮以及解壓
利用Java的I/O流實作圖檔的壓縮以及解壓
解壓結果以及解壓時間:
利用Java的I/O流實作圖檔的壓縮以及解壓
利用Java的I/O流實作圖檔的壓縮以及解壓