使用Zip4j压缩指向目录的符号链接失败,求解决方法
Zip4j 保留指向目录的符号链接问题解决方案
我明白你想要用Zip4j实现和zip -yr完全一致的符号链接压缩效果,尤其是保留指向目录的软链接。你当前的代码已经处理了普通文件的软链接,但指向目录的软链接没被正确识别,核心原因是Zip4j需要明确知道这个软链接是指向目录的,才能在压缩包中标记它为目录型链接。
问题分析
当你处理指向目录的软链接b时,代码只判断了它是符号链接,但没有告诉Zip4j这个链接的目标是目录——Zip4j会默认把它当成普通文件处理,解压时就不会重建目录链接,而是把它当成普通文件提取。
修正后的代码
我们需要添加逻辑:读取符号链接的目标,判断目标是否为目录,如果是,就给压缩后的文件名加上/后缀,同时保持符号链接的参数设置:
import net.lingala.zip4j.ZipFile; import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.model.ZipParameters; import net.lingala.zip4j.model.enums.CompressionLevel; import net.lingala.zip4j.model.enums.CompressionMethod; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; public class ZipTest { public static void main(String[] args) throws IOException { try (ZipFile zipFile = new ZipFile("test.zip"); Stream<Path> paths = Files.walk(Paths.get("tmp"))) { paths.forEach(path -> { ZipParameters zp = new ZipParameters(); String fileNameInZip = path.toString(); // 处理普通目录:添加/后缀标识 if (!Files.isSymbolicLink(path) && Files.isDirectory(path)) { fileNameInZip += "/"; } // 处理符号链接:判断目标是否为目录,是则添加/后缀 else if (Files.isSymbolicLink(path)) { try { Path target = Files.readSymbolicLink(path); // 解析完整的目标路径(处理相对路径) Path fullTarget = path.getParent().resolve(target).normalize(); if (Files.isDirectory(fullTarget)) { fileNameInZip += "/"; } } catch (IOException e) { throw new RuntimeException("Failed to read symbolic link target", e); } // 保持符号链接的专属配置,只压缩链接本身 zp.setSymbolicLinkAction(ZipParameters.SymbolicLinkAction.INCLUDE_LINK_ONLY); zp.setCompressionLevel(CompressionLevel.NO_COMPRESSION); zp.setCompressionMethod(CompressionMethod.STORE); } zp.setFileNameInZip(fileNameInZip); try { zipFile.addFile(path.toFile(), zp); } catch (ZipException e) { throw new RuntimeException("Failed to add file to zip", e); } }); } } }
关键调整点
- 识别目录型符号链接:通过
Files.readSymbolicLink读取链接目标,判断目标是否为目录,若是则给fileNameInZip添加/——这是让Zip4j正确识别它为目录链接的核心 - 保持符号链接参数:
INCLUDE_LINK_ONLY确保只压缩链接本身,不递归解压目标目录,和zip -y的行为一致 - 压缩配置:
STORE和NO_COMPRESSION对应zip命令的默认行为,不对链接文件进行压缩
验证结果
运行修正后的代码生成test.zip,然后解压:
$ unzip test.zip -d test Archive: test.zip creating: test/tmp/ creating: test/tmp/a/ extracting: test/tmp/c linking: test/tmp/d -> c linking: test/tmp/b -> a finishing deferred symbolic links: test/tmp/d -> c test/tmp/b -> a
现在指向目录的软链接b会被正确保留,和zip -yr的效果完全一致。
内容的提问来源于stack exchange,提问作者Nold
相关产品推荐
相关产品推荐

