ZipUtil.java 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. package com.fdkankan.contro.util;
  2. import cn.hutool.core.io.FileUtil;
  3. import cn.hutool.core.io.IoUtil;
  4. import com.fdkankan.contro.constant.ZipConstant;
  5. import net.lingala.zip4j.ZipFile;
  6. import net.lingala.zip4j.model.FileHeader;
  7. import java.io.File;
  8. import java.io.InputStream;
  9. import java.nio.charset.Charset;
  10. import java.nio.file.Paths;
  11. import java.util.Enumeration;
  12. import java.util.List;
  13. import java.util.zip.ZipEntry;
  14. public class ZipUtil {
  15. public static void main(String[] args) throws Exception {
  16. // 压缩包路径
  17. String zipPath = "D:\\Downloads\\各类相机从App导出的原始数据\\bpvt00017_20250314173801715_meta\\bpvt00017_20250314173801715.zip";
  18. System.out.println(readUtf8(zipPath, "data.fdage"));
  19. }
  20. public static String readUtf8(String zipPath, String fileName) throws Exception {
  21. ZipFile zipFile = new ZipFile(zipPath);
  22. zipFile.setPassword(ZipConstant.zipPassword.toCharArray());
  23. // 读取所有条目(文件头)
  24. for (FileHeader header : (List<FileHeader>)zipFile.getFileHeaders()) {
  25. // 文件名(不含目录)
  26. String filePath = header.getFileName();
  27. String headerFileName = FileUtil.getName(filePath);
  28. if (filePath.contains("backup") || !fileName.equals(headerFileName)) {
  29. continue;
  30. }
  31. try (InputStream is = zipFile.getInputStream(header)) {
  32. return IoUtil.readUtf8(is);
  33. }
  34. }
  35. return null;
  36. }
  37. /**
  38. * 解压 zip 压缩包到目标目录
  39. * @param zipFilePath 压缩包路径
  40. * @param destDirPath 解压目录
  41. */
  42. public static void unzip(String zipFilePath, String destDirPath) {
  43. File zipFile = new File(zipFilePath);
  44. File destDir = new File(destDirPath);
  45. // 自动检测编码,常见 GBK / UTF-8
  46. Charset charset = detectCharset(zipFile);
  47. // 解压(如果是 Windows 打包的 zip,GBK 最常见)
  48. cn.hutool.core.util.ZipUtil.unzip(zipFile, destDir, charset);
  49. }
  50. /**
  51. * 检测 ZIP 文件的编码(仅用于文件名编码判断)
  52. * 逻辑:UTF-8 -> GBK -> default
  53. * @param zipFile ZIP 文件
  54. * @return Charset 识别到的编码
  55. */
  56. public static Charset detectCharset(File zipFile) {
  57. // 1. 尝试 UTF-8
  58. if (isCharset(zipFile, Charset.forName("UTF-8"))) {
  59. return Charset.forName("UTF-8");
  60. }
  61. // 2. 尝试 GBK(Windows zip 默认编码)
  62. if (isCharset(zipFile, Charset.forName("GBK"))) {
  63. return Charset.forName("GBK");
  64. }
  65. // 3. 都不行 → 返回系统默认
  66. return Charset.defaultCharset();
  67. }
  68. /**
  69. * 判断使用该编码读取 ZIP 是否正常(没有乱码字符)
  70. */
  71. private static boolean isCharset(File zipFile, Charset charset) {
  72. try (java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFile, charset)) {
  73. Enumeration<? extends ZipEntry> entries = zf.entries();
  74. while (entries.hasMoreElements()) {
  75. ZipEntry entry = entries.nextElement();
  76. // 只检查名字,不读取内容
  77. String name = entry.getName();
  78. // 若名字中出现 �(替换字符),说明编码不对
  79. if (name.contains("\uFFFD")) {
  80. return false;
  81. }
  82. }
  83. return true;
  84. } catch (Exception e) {
  85. // 出现异常说明该编码不匹配
  86. return false;
  87. }
  88. }
  89. }