一、JAVA主流压缩工具
-
java.util.zip:
**说明:**Java标准库提供的压缩与解压功能,包含在
java.util.zip
包中。通过ZipInputStream
和ZipOutputStream
可以实现ZIP格式的压缩与解压缩操作。适用场景: 适合简单的ZIP格式压缩与解压缩操作,可用于对单个文件或目录进行压缩和解压缩。
-
Apache Commons Compress:
**说明:**Apache Commons Compress是Apache软件基金会提供的开源压缩与解压工具包,支持多种压缩格式,包括ZIP、Gzip、Tar等。通过该工具包,可以进行更复杂的压缩与解压缩操作。
**适用场景:**支持多种压缩格式,如ZIP、Gzip、Tar等,适合复杂的压缩与解压缩操作,可用于处理各种压缩格式和对多个文件或目录进行打包、解压缩。
-
Java Zip4j:
**说明:**Zip4j是一个开源的Java库,提供了对ZIP格式的支持,并且支持密码保护、分卷压缩等功能。
**适用场景:**支持ZIP格式,提供了一些高级功能,如密码保护、分卷压缩等,适合复杂的ZIP格式的压缩与解压缩操作。
-
LZ4:
**说明:**LZ4是一种高性能的压缩算法,具有快速的压缩和解压缩速度,但压缩比相对较低。
**适用场景:**适合对大量数据进行实时压缩和解压缩,例如在网络传输或大数据处理中,追求较高的压缩/解压缩速度。
-
Snappy
**说明:**Snappy是一种快速的压缩和解压缩算法,具有较快的压缩和解压缩速度,适合高性能场景。
**适用场景:**适用于对大规模数据进行实时压缩和解压缩,例如在大数据处理和分析中。
这些压缩与解压工具可以根据项目的需求和使用场景选择合适的工具进行压缩与解压缩操作。Java标准库的java.util.zip
包通常适用于简单的ZIP格式压缩与解压缩,Apache Commons Compress和Java Zip4j提供了更多的压缩格式和功能选项。对于大型数据集和高性能要求的场景,还可以考虑使用专门的压缩工具或算法,如LZ4、Snappy等。
二、压缩与解压用法
-
java.util.zip的使用
import java.io.*; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import java.util.zip.ZipOutputStream; public class JavaUtilZipDemo { /** * 使用java.util.zip库进行文件压缩 * * @param inputFile 要压缩的文件或目录 * @param outputFile 压缩后的文件 * @throws IOException 压缩过程中可能出现的异常 */ public static void zipCompress(File inputFile, File outputFile) throws IOException { // 创建输出流写入压缩后的文件 try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(outputFile))) { // 判断要压缩的是文件还是目录 if (inputFile.isFile()) { // 压缩文件 zipFile(inputFile, zos, ""); } else if (inputFile.isDirectory()) { // 压缩目录 zipDir(inputFile, zos, ""); } } } /** * 递归压缩目录及其子目录和文件 * * @param dir 要压缩的目录 * @param zos 压缩输出流 * @param entry 压缩实体 * @throws IOException 压缩过程中可能出现的异常 */ private static void zipDir(File dir, ZipOutputStream zos, String entry) throws IOException { // 获取目录中的文件和子目录 File[] files = dir.listFiles(); if (files != null) { for (File file : files) { if (file.isFile()) { // 压缩文件 zipFile(file, zos, entry + file.getName()); } else if (file.isDirectory()) { // 压缩子目录 zipDir(file, zos, entry + file.getName() + "/"); } } } } /** * 压缩文件 * * @param file 要压缩的文件 * @param zos 压缩输出流 * @param entry 压缩实体 * @throws IOException 压缩过程中可能出现的异常 */ private static void zipFile(File file, ZipOutputStream zos, String entry) throws IOException { // 创建压缩实体并设置实体名称 ZipEntry zipEntry = new ZipEntry(entry); // 将压缩实体写入压缩输出流 zos.putNextEntry(zipEntry); // 创建输入流读取文件内容,并将内容写入压缩输出流 try (FileInputStream fis = new FileInputStream(file)) { byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) > 0) { zos.write(buffer, 0, length); } } // 关闭当前压缩实体 zos.closeEntry(); } /** * 使用java.util.zip库进行文件解压缩 * * @param inputFile 压缩文件 * @param outputDir 解压后的目录 * @throws IOException 解压过程中可能出现的异常 */ public static void zipDecompress(File inputFile, File outputDir) throws IOException { // 创建输入流读取压缩文件 try (ZipInputStream zis = new ZipInputStream(new FileInputStream(inputFile))) { // 遍历压缩文件中的实体 ZipEntry zipEntry; while ((zipEntry = zis.getNextEntry()) != null) { // 获取实体的名称 String entryName = zipEntry.getName(); // 创建输出文件并设置输出目录 File outputFile = new File(outputDir, entryName); // 如果实体是目录,则创建相应目录;否则创建输出文件并写入数据 if (zipEntry.isDirectory()) { outputFile.mkdirs(); } else { try (FileOutputStream fos = new FileOutputStream(outputFile)) { // 将输入流的数据写入输出文件 byte[] buffer = new byte[1024]; int length; while ((length = zis.read(buffer)) > 0) { fos.write(buffer, 0, length); } } } // 关闭当前解压实体 zis.closeEntry(); } } } public static void main(String[] args) { try { File inputFile = new File("input"); File outputFile = new File("output.zip"); File outputDir = new File("output"); // 压缩文件或目录 zipCompress(inputFile, outputFile); // 解压缩文件 zipDecompress(outputFile, outputDir); } catch (IOException e) { e.printStackTrace(); } } }
-
Apache Commons Compress的使用
import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; import org.apache.commons.compress.utils.IOUtils; import java.io.*; public class CommonsCompressUtil { /** * 使用 Apache Commons Compress 库进行Gzip压缩 * * @param inputFile 要压缩的文件 * @param outputFile 压缩后的文件 * @throws IOException 压缩过程中可能出现的异常 */ public static void gzipCompress(File inputFile, File outputFile) throws IOException { // 创建输入流读取要压缩的文件 try (FileInputStream fis = new FileInputStream(inputFile); // 创建压缩输出流写入压缩后的文件 GzipCompressorOutputStream gzos = new GzipCompressorOutputStream(new FileOutputStream(outputFile))) { // 将输入流的数据压缩并写入输出流 IOUtils.copy(fis, gzos); } } /** * 使用 Apache Commons Compress 库进行Gzip解压缩 * * @param inputFile 压缩文件 * @param outputFile 解压后的文件 * @throws IOException 解压过程中可能出现的异常 */ public static void gzipDecompress(File inputFile, File outputFile) throws IOException { // 创建输入流读取压缩文件 try (GzipCompressorInputStream gzis = new GzipCompressorInputStream(new FileInputStream(inputFile)); // 创建输出流写入解压后的文件 FileOutputStream fos = new FileOutputStream(outputFile)) { // 将输入流的数据解压并写入输出流 IOUtils.copy(gzis, fos); } } /** * 使用 Apache Commons Compress 库进行Tar压缩 * * @param inputFiles 要压缩的文件列表 * @param outputFile 压缩后的文件 * @throws IOException 压缩过程中可能出现的异常 */ public static void tarCompress(File[] inputFiles, File outputFile) throws IOException { // 创建压缩输出流写入压缩后的文件 try (TarArchiveOutputStream taros = new TarArchiveOutputStream(new FileOutputStream(outputFile))) { // 设置压缩格式为gzip taros.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); // 遍历要压缩的文件列表 for (File inputFile : inputFiles) { // 创建压缩实体并设置文件名 ArchiveEntry entry = taros.createArchiveEntry(inputFile, inputFile.getName()); // 将实体写入压缩输出流 taros.putArchiveEntry(entry); // 创建输入流读取要压缩的文件 try (FileInputStream fis = new FileInputStream(inputFile)) { // 将输入流的数据写入压缩输出流 IOUtils.copy(fis, taros); } // 关闭当前压缩实体 taros.closeArchiveEntry(); } } } /** * 使用 Apache Commons Compress 库进行Tar解压缩 * * @param inputFile 压缩文件 * @param outputDir 解压后的目录 * @throws IOException 解压过程中可能出现的异常 */ public static void tarDecompress(File inputFile, File outputDir) throws IOException { // 创建输入流读取压缩文件 try (TarArchiveInputStream taris = new TarArchiveInputStream(new FileInputStream(inputFile))) { // 遍历压缩文件中的实体 ArchiveEntry entry; while ((entry = taris.getNextEntry()) != null) { // 获取实体的文件名 String fileName = entry.getName(); // 创建输出文件并设置输出目录 File outputFile = new File(outputDir, fileName); // 如果实体是目录,则创建相应目录;否则创建输出文件并写入数据 if (entry.isDirectory()) { outputFile.mkdirs(); } else { try (FileOutputStream fos = new FileOutputStream(outputFile)) { // 将输入流的数据写入输出文件 IOUtils.copy(taris, fos); } } } } } public static void main(String[] args) { try { File inputFile = new File("input.txt"); File gzipFile = new File("output.gz"); File outputFile = new File("output.txt"); File[] tarInputFiles = {new File("file1.txt"), new File("file2.txt")}; File tarFile = new File("output.tar"); // Gzip压缩 gzipCompress(inputFile, gzipFile); // Gzip解压缩 gzipDecompress(gzipFile, outputFile); // Tar压缩 tarCompress(tarInputFiles, tarFile); // Tar解压缩 tarDecompress(tarFile, new File("outputDir")); } catch (IOException e) { e.printStackTrace(); } } }
-
Zip4j使用:
import net.lingala.zip4j.ZipFile; import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.util.Zip4jConstants; import java.io.File; public class Zip4jUtil { public static void compress(String sourceDir, String zipFile, String password) throws ZipException { // 创建 ZipFile 对象,指定要生成的压缩文件 ZipFile zip = new ZipFile(zipFile); // 设置压缩参数 ZipParameters parameters = new ZipParameters(); parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // 设置压缩方法 parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); // 设置压缩级别 if (password != null && !password.isEmpty()) { parameters.setEncryptFiles(true); // 设置是否加密文件 parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD); // 设置加密方法 parameters.setPassword(password); // 设置密码 } // 添加要压缩的文件或文件夹 File sourceFile = new File(sourceDir); zip.addFolder(sourceFile, parameters); } public static void decompress(String zipFile, String destDir, String password) throws ZipException { // 创建 ZipFile 对象,指定要解压缩的文件 ZipFile zip = new ZipFile(zipFile); // 设置解压密码(如果有) if (password != null && !password.isEmpty()) { if (zip.isEncrypted()) { zip.setPassword(password); } else { throw new ZipException("压缩文件未加密,请检查密码设置。"); } } // 解压缩文件到指定目录 zip.extractAll(destDir); } public static void main(String[] args) { try { String sourceDir = "source_directory"; String zipFile = "compressed.zip"; String destDir = "destination_directory"; String password = "123456"; // 设置压缩密码,如果不需要加密可以设为null或空字符串 // 压缩 compress(sourceDir, zipFile, password); // 解压缩 decompress(zipFile, destDir, password); } catch (ZipException e) { e.printStackTrace(); } } }
-
LZ4的使用:
import net.jpountz.lz4.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; public class LZ4Util { /** * 使用 LZ4 算法压缩数据 * * @param data 要压缩的数据 * @return 压缩后的数据 * @throws IOException 压缩过程中可能出现的异常 */ public static byte[] compress(byte[] data) throws IOException { // 获取 LZ4 算法的压缩器 LZ4Compressor compressor = LZ4Factory.fastestInstance().fastCompressor(); // 计算压缩后的数据最大长度 int maxCompressedLength = compressor.maxCompressedLength(data.length); // 创建一个缓冲区用于存储压缩后的数据 byte[] compressedData = new byte[maxCompressedLength]; // 进行压缩,并获取压缩后的数据长度 int compressedLength = compressor.compress(data, 0, data.length, compressedData, 0); // 根据实际压缩后的数据长度,创建一个新的数组来存储压缩后的数据 byte[] result = new byte[compressedLength]; System.arraycopy(compressedData, 0, result, 0, compressedLength); return result; } /** * 使用 LZ4 算法解压数据 * * @param compressedData 压缩后的数据 * @param originalLength 原始数据的长度 * @return 解压后的数据 * @throws IOException 解压过程中可能出现的异常 */ public static byte[] decompress(byte[] compressedData, int originalLength) throws IOException { // 获取 LZ4 算法的解压缩器 LZ4FastDecompressor decompressor = LZ4Factory.fastestInstance().fastDecompressor(); // 创建一个新的数组,用于存储解压后的数据 byte[] result = new byte[originalLength]; // 进行解压缩 decompressor.decompress(compressedData, 0, result, 0, originalLength); return result; } public static void main(String[] args) { try { String inputString = "Hello, LZ4 compression!"; byte[] inputData = inputString.getBytes(); // 压缩 byte[] compressedData = compress(inputData); // 解压缩 byte[] decompressedData = decompress(compressedData, inputData.length); System.out.println("原始数据:" + inputString); System.out.println("压缩后数据:" + new String(compressedData)); System.out.println("解压缩后数据:" + new String(decompressedData)); } catch (IOException e) { e.printStackTrace(); } } }
-
Snappy的使用
import org.xerial.snappy.Snappy; import java.io.IOException; public class SnappyUtil { /** * 使用 Snappy 算法压缩数据 * * @param data 要压缩的数据 * @return 压缩后的数据 * @throws IOException 压缩过程中可能出现的异常 */ public static byte[] compress(byte[] data) throws IOException { // 调用 Snappy 的压缩方法进行数据压缩 return Snappy.compress(data); } /** * 使用 Snappy 算法解压数据 * * @param compressedData 压缩后的数据 * @return 解压后的数据 * @throws IOException 解压过程中可能出现的异常 */ public static byte[] decompress(byte[] compressedData) throws IOException { // 调用 Snappy 的解压方法进行数据解压缩 return Snappy.uncompress(compressedData); } public static void main(String[] args) { try { String inputString = "Hello, Snappy compression!"; byte[] inputData = inputString.getBytes(); // 压缩 byte[] compressedData = compress(inputData); // 解压缩 byte[] decompressedData = decompress(compressedData); System.out.println("原始数据:" + inputString); System.out.println("压缩后数据:" + new String(compressedData)); System.out.println("解压缩后数据:" + new String(decompressedData)); } catch (IOException e) { e.printStackTrace(); } } }
三、综合比较与选取
压缩算法 | 原始数据大小 | 压缩后数据大小 | 解压缩次数 | 耗时(ms) |
---|---|---|---|---|
common-compress(bzip2) | 3260 | 586 | 10000 | 2361/2852/2676/2138 |
gzip | 3260 | 590 | 10000 | 171/163/152/146/148 |
lz4 | 3260 | 1103 | 10000 | 61/60/62/73/63 |
snappy | 3260 | 1056 | 10000 | 36/39/33/33/33 |
总结以上工具的特点如下:
- java.util.zip:Java标准库提供的压缩与解压工具,使用简单方便,适用于基本的压缩与解压需求,但性能较其他库稍逊。
- Apache Commons Compress:功能丰富的开源压缩库,支持多种压缩格式,包括zip、tar、gzip、bzip2等,适用于处理各种类型的压缩文件,性能较好。
- Zip4j:基于java.util.zip的封装库,提供更便捷的API,支持密码保护和分卷压缩等功能,适用于需要额外功能的压缩需求。
- LZ4:高压缩速度和解压速度的压缩库,适用于大规模数据压缩和快速数据传输场景,但压缩比较低。
- Snappy:极高的压缩速度和较好的解压速度,适用于低延迟的数据传输场景,但压缩比较低。
综合选择压缩工具时,可以根据实际需求权衡性能和功能。如果需要高性能的压缩和解压速度,可以选择LZ4或Snappy;如果需要支持更多的压缩格式和功能,可以选择Apache Commons Compress或Zip4j;如果仅需简单的压缩和解压操作,可以使用java.util.zip。
注意:即便同一种压缩格式,比如zip, 也会有不同的版本,如果采用jdk或zip4j可能并不能成功解压, 如果需要更好的兼容与稳定性, 可以采用Apache Commons Compress进行解压处理。