java解压zip文件并为文件添加前缀

要在Java中解压ZIP文件时考虑以上所有要求,我们需要确保使用正确的编码来读取文件名,并且一旦检测到文件大小不符合要求,我们就需要停止解压并清理已解压的文件。下面是一个改进后的示例代码:

import java.io.*;  
import java.nio.charset.StandardCharsets;  
import java.nio.file.*;  
import java.util.ArrayList;  
import java.util.List;  
import java.util.zip.ZipEntry;  
import java.util.zip.ZipInputStream;  
  
public class ZipExtractor {  
  
    private static final long MIN_FILE_SIZE = 40 * 1024; // 40K  
    private static final long MAX_FILE_SIZE = 200 * 1024; // 200K  
    private static final String PREFIX = "your_prefix_"; // 替换为你的前缀  
  
    /**
     * 解压文件并重命名解压出来的文件
     *
     * @param zipFile       要解压的文件
     * @param destDirectory 解压位置
     * @param prefix        前缀
     */
    public static void unzipAndRename(File zipFile, String destDirectory, String prefix) throws IOException {
        List<File> extractedFiles = new ArrayList<>(); // 跟踪已解压的文件
        try (ZipFile zip = new ZipFile(zipFile, Charset.forName("GBK"))) {
            // 确保目标目录存在
            File dir = new File(destDirectory);
            if (!dir.exists() && !dir.mkdirs()) {
                throw new RuntimeException("创建文件夹失败");
            }
            // 遍历ZIP文件中的所有条目
            Enumeration<? extends ZipEntry> entries = zip.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                String fileName = entry.getName();
                long max_file_size = 200 * 1024; // 200K
                long min_file_size = 40 * 1024; // 40K
                // 检查文件大小
                if (entry.getSize() < min_file_size || entry.getSize() > max_file_size) {
                    throw new IOException("文件大小不在要求的范围内: " + fileName);
                }
                // 重新命名文件(如果需要)
                if (!fileName.startsWith(prefix)) {
                    fileName = prefix + fileName;
                }
                File entryDestination = new File(destDirectory, fileName);
                extractedFiles.add(entryDestination); // 添加已解压文件到列表
                if (!entry.isDirectory()){
                    entryDestination.mkdirs();
                }else {
                    entryDestination.getParentFile().mkdirs();
                    try (InputStream in = zip.getInputStream(entry);
                         FileOutputStream out = new FileOutputStream(entryDestination)) {
                        byte[] buffer = new byte[2048];
                        int length;
                        while ((length = in.read(buffer)) > 0) {
                            out.write(buffer, 0, length);
                        }
                    }
                }
            }
        } catch (IOException e) {
            // 如果有任何文件大小不符合要求,删除已解压的文件
            if (e.getMessage().contains("文件大小不在要求的范围内")) {
                for (File file : extractedFiles) {
                    if (file.exists() && file.delete()) {
                        System.out.println("Deleted: " + file.getAbsolutePath());
                    }
                }
            }
            throw e;
        }
    }
  
    public static void main(String[] args) {  
        String zipFilePath = "path_to_your_zip_file.zip"; // 替换为你的ZIP文件路径  
        String destDir = "path_to_extract_directory"; // 替换为解压目标目录  
  
        try {  
            extractZip(zipFilePath, destDir, PREFIX);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}

请注意以下几点:

  1. 我们使用StandardCharsets.GBK作为ZipInputStream的第二个参数来确保文件名以GBK编码读取,从而防止中文乱码。但是,不是所有的ZIP文件都会以GBK编码其文件名,这取决于创建ZIP文件的系统。如果ZIP文件中的文件名使用的是UTF-8或其他编码,你需要相应地更改。

  2. 我们维护了一个List<File>来跟踪已解压的文件,并在检测到不符合要求的文件大小时删除它们。

  3. 在实际生产环境中,你可能需要更复杂的错误处理逻辑,比如记录日志、通知用户等。

  4. 请确保你有足够的权限来删除文件,否则file.delete()方法将不会成功。

  5. 如果ZIP文件非常大,你可能需要考虑在解压过程中使用更高效的内存管理策略,比如流式处理文件内容而不是一次性加载整个文件到内存中。


标签:
评论 (0)
说点什么吧... (取消回复)