Java实现文件的压缩并加密

目录

目的

实现

方式一:使用Zip4j库实现

1. 添加依赖

 2. 实现代码

方式二:使用Java内置库实现(无加密)

压缩文件(无加密)

可能的问题和解决方案

1. 密码设置为空或null

2. 解压工具不支持加密ZIP

3. 加密参数未正确设置

 4. 测试加密是否成功的完整示例

5.注意事项

 效果展示

目的

        在服务器的文件比较敏感的时候,进行备份的时候考虑到文件的隐私性,可以考虑先用java对文件夹或者文件进行压缩后再进行加密保证数据的安全性。

实现

方式一:使用Zip4j库实现

        Zip4j是一个流行的Java库,支持带密码保护的ZIP文件创建和提取。

1. 添加依赖

首先,在你的项目中添加Zip4j依赖:

Maven:

<dependency>
    <groupId>net.lingala.zip4j</groupId>
    <artifactId>zip4j</artifactId>
    <version>2.11.5</version>
</dependency>

Gradle:

implementation 'net.lingala.zip4j:zip4j:2.11.5'

 2. 实现代码

import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.AesKeyStrength;
import net.lingala.zip4j.model.enums.EncryptionMethod;

import java.io.File;

public class ZipWithPassword {

    /**
     * 压缩文件或目录并加密
     * @param sourcePath 要压缩的文件或目录路径
     * @param outputZipPath 输出的ZIP文件路径
     * @param password 加密密码
     * @throws ZipException 如果压缩过程中出现错误
     */
    public static void zipWithPassword(String sourcePath, String outputZipPath, String password) throws ZipException {
        try {
            // 创建ZipFile对象
            ZipFile zipFile = new ZipFile(outputZipPath, password.toCharArray());
            
            // 设置加密参数
            ZipParameters parameters = new ZipParameters();
            parameters.setEncryptFiles(true);
            parameters.setEncryptionMethod(EncryptionMethod.AES);
            parameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256);
            
            File sourceFile = new File(sourcePath);
            
            if (sourceFile.isDirectory()) {
                // 压缩目录
                zipFile.addFolder(sourceFile, parameters);
            } else {
                // 压缩单个文件
                zipFile.addFile(sourceFile, parameters);
            }
            
            System.out.println("文件压缩并加密成功: " + outputZipPath);
        } catch (ZipException e) {
            System.err.println("压缩失败: " + e.getMessage());
            throw e;
        }
    }

    public static void main(String[] args) {
        try {
            // 示例用法
            String source = "path/to/your/file_or_directory"; // 替换为实际路径
            String output = "output.zip"; // 输出ZIP文件路径
            String password = "yourPassword123"; // 设置密码
            
            zipWithPassword(source, output, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

方式二:使用Java内置库实现(无加密)

        如果你不想使用第三方库,Java内置的java.util.zip包可以处理ZIP文件,但不支持密码加密。如果需要加密,你可以先压缩再使用加密算法加密整个ZIP文件。

压缩文件(无加密)

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipUtility {

    public static void zipFile(String sourceFilePath, String zipFilePath) throws IOException {
        FileOutputStream fos = new FileOutputStream(zipFilePath);
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        
        File fileToZip = new File(sourceFilePath);
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
        zipOut.putNextEntry(zipEntry);
        
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipOut.write(bytes, 0, length);
        }
        
        fis.close();
        zipOut.close();
        fos.close();
    }

    public static void zipDirectory(String sourceDirectoryPath, String zipFilePath) throws IOException {
        FileOutputStream fos = new FileOutputStream(zipFilePath);
        ZipOutputStream zipOut = new ZipOutputStream(fos);
        
        File fileToZip = new File(sourceDirectoryPath);
        zipFile(fileToZip, fileToZip.getName(), zipOut);
        
        zipOut.close();
        fos.close();
    }

    private static void zipFile(File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
        if (fileToZip.isHidden()) {
            return;
        }
        
        if (fileToZip.isDirectory()) {
            if (fileName.endsWith("/")) {
                zipOut.putNextEntry(new ZipEntry(fileName));
                zipOut.closeEntry();
            } else {
                zipOut.putNextEntry(new ZipEntry(fileName + "/"));
                zipOut.closeEntry();
            }
            
            File[] children = fileToZip.listFiles();
            for (File childFile : children) {
                zipFile(childFile, fileName + "/" + childFile.getName(), zipOut);
            }
            return;
        }
        
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileName);
        zipOut.putNextEntry(zipEntry);
        
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipOut.write(bytes, 0, length);
        }
        fis.close();
    }

    public static void main(String[] args) {
        try {
            // 压缩文件示例
            zipFile("file.txt", "compressed.zip");
            
            // 压缩目录示例
            zipDirectory("myDirectory", "compressedDir.zip");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

可能的问题和解决方案

        使用Zip4j创建的加密ZIP文件在解压时应该需要输入密码,如果不需要,可能是以下原因导致的:

1. 密码设置为空或null

如果您在代码中传递了空密码或null,Zip4j会创建不加密的ZIP文件。

解决方案:确保密码不为空且长度足够:

if (password == null || password.trim().isEmpty()) {
    throw new IllegalArgumentException("密码不能为空");
}

2. 解压工具不支持加密ZIP

某些简易解压工具可能无法识别加密的ZIP文件,会直接解压而不提示输入密码。

解决方案

  • 使用支持加密ZIP的工具测试(如7-Zip、WinRAR或Zip4j本身)

  • 用以下代码测试解压:

public static void testZipPassword(String zipPath, String password) throws ZipException {
    ZipFile zipFile = new ZipFile(zipPath);
    if (zipFile.isEncrypted()) {
        System.out.println("ZIP文件已加密");
        zipFile.setPassword(password.toCharArray());
    }
    
    // 尝试列出文件(会验证密码)
    zipFile.getFileHeaders().forEach(header -> {
        System.out.println(header.getFileName());
    });
    
    System.out.println("密码验证成功!");
}

3. 加密参数未正确设置

虽然ZipParameters设置了加密,但可能在创建ZipFile时没有正确应用。

完整正确示例

public static void secureZipWithPassword(String sourcePath, String outputZipPath, String password) 
    throws ZipException {
    
    // 验证密码
    if (password == null || password.trim().isEmpty()) {
        throw new IllegalArgumentException("密码不能为空");
    }
    
    try {
        // 方法1:创建时直接指定密码(推荐)
        ZipFile zipFile = new ZipFile(outputZipPath, password.toCharArray());
        
        // 方法2:或者创建后设置密码
        // ZipFile zipFile = new ZipFile(outputZipPath);
        // zipFile.setPassword(password.toCharArray());
        
        ZipParameters parameters = new ZipParameters();
        parameters.setEncryptFiles(true);
        parameters.setEncryptionMethod(EncryptionMethod.AES); // 必须使用AES加密
        parameters.setAesKeyStrength(AesKeyStrength.KEY_STRENGTH_256); // 256位加密
        
        File sourceFile = new File(sourcePath);
        if (sourceFile.isDirectory()) {
            zipFile.addFolder(sourceFile, parameters);
        } else {
            zipFile.addFile(sourceFile, parameters);
        }
        
        System.out.println("成功创建加密ZIP: " + outputZipPath);
        
        // 验证文件确实已加密
        if (zipFile.isEncrypted()) {
            System.out.println("验证: 文件已加密");
        } else {
            System.err.println("警告: 文件未加密!");
        }
    } catch (ZipException e) {
        System.err.println("加密压缩失败: " + e.getMessage());
        throw e;
    }
}

 4. 测试加密是否成功的完整示例

public static void main(String[] args) {
    try {
        String source = "test.txt";
        String output = "encrypted.zip";
        String password = "strongPassword123!";
        
        // 1. 创建加密ZIP
        secureZipWithPassword(source, output, password);
        
        // 2. 测试解压(应该需要密码)
        System.out.println("\n尝试无密码解压...");
        try {
            new ZipFile(output).extractAll("unzipped_no_password");
            System.err.println("错误: 无密码解压成功!");
        } catch (ZipException e) {
            System.out.println("预期错误: " + e.getMessage());
        }
        
        // 3. 用正确密码解压
        System.out.println("\n用正确密码解压...");
        new ZipFile(output, password.toCharArray()).extractAll("unzipped_with_password");
        System.out.println("成功用密码解压");
        
    } catch (Exception e) {
        e.printStackTrace();
    }
}

5.注意事项

  1. 对于生产环境,建议使用成熟的第三方库如Zip4j,因为它们提供了更好的加密支持和错误处理。

  2. 密码保护的安全性取决于加密算法的强度,Zip4j使用AES加密,这是目前较为安全的选择。

  3. 处理大文件时,注意内存使用,使用缓冲区并适当调整缓冲区大小。

  4. 记得在完成后关闭所有流资源,防止资源泄漏。

 效果展示 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值