You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在D盘根目录创建TrueZip归档文件?

如何在D盘根目录使用TrueZip创建归档文件?

我之前也踩过TrueZip这个坑!它对系统盘的根目录(比如D:\这种顶级目录)有默认的保护机制,哪怕你的D盘只是用来存个人数据,它也会把这里识别为「系统文件系统根」,限制直接创建新的归档文件——这就是你看到FsArchiveFileSystemException: <file system root> (only files can get replaced)错误的核心原因:TrueZip只允许替换根目录下已存在的文件,不允许新建。

下面给你几个可行的解决方案,结合你的代码来调整:

方案1:提前创建空归档文件,再用TrueZip替换它

既然TrueZip允许替换根目录已存在的文件,那我们可以先通过代码创建一个空的zip文件占位,再让TrueZip往里面写入内容。修改你的代码如下:

public static void main(String[] args) throws IOException {
    JFileChooser chooser = new JFileChooser();
    chooser.setDialogTitle("Please select the target folder.");
    chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
    JFrame applicationFrame = new JFrame();
    if (chooser.showSaveDialog(applicationFrame) != JFileChooser.APPROVE_OPTION) return;
    File selectedFile = chooser.getSelectedFile();
    String zipPath = selectedFile + ".zip";
    File tempZip = new File(zipPath);
    
    // 检查目标文件是否在磁盘根目录
    File parentDir = tempZip.getParentFile();
    if (parentDir != null && parentDir.getAbsolutePath().matches("^[A-Za-z]:\\\\$")) {
        // 先创建空的zip文件占位
        try (OutputStream os = new FileOutputStream(tempZip)) {
            // 仅创建文件,无需写入内容
        } catch (IOException e) {
            JOptionPane.showMessageDialog(applicationFrame, "无法创建空文件:" + e.getMessage());
            return;
        }
    }
    
    TFile archiveFile = new TFile(zipPath);
    System.out.println("Selected file: " + archiveFile.getAbsolutePath());
    ZipOutputStream zipOutputStream = new ZipOutputStream(new TFileOutputStream(archiveFile));
    
    // 新增空判断,避免files为null时抛出异常
    File folderToZip = new File("D:/filesToZip");
    File[] files = folderToZip.listFiles();
    if (files != null) {
        for (File file : files) {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            int avail = bis.available();
            byte[] buffer = new byte[avail];
            if (avail > 0) {
                bis.read(buffer, 0, avail);
            }
            bis.close();
            ZipEntry zipEntry = new ZipEntry(file.getName());
            zipOutputStream.putNextEntry(zipEntry);
            zipOutputStream.write(buffer, 0, buffer.length);
            zipOutputStream.closeEntry();
        }
    }
    zipOutputStream.close();
    System.exit(0);
}

方案2:将归档文件放在D盘的子目录中

这是更简单稳妥的办法,直接避开根目录的特殊限制。你可以引导用户选择D盘下的子文件夹(比如D:\Archives),或者在代码里自动处理:如果用户选了根目录,就自动创建一个子目录来存放归档文件。

修改代码中处理选中文件的部分:

File selectedFile = chooser.getSelectedFile();
File parentDir = selectedFile.getParentFile();
// 判断是否选中了磁盘根目录
if (parentDir != null && parentDir.getAbsolutePath().matches("^[A-Za-z]:\\\\$")) {
    // 创建默认的归档存储子目录
    File subDir = new File(parentDir, "ArchiveFiles");
    if (!subDir.exists()) {
        subDir.mkdirs(); // 递归创建目录
    }
    // 将目标文件路径转移到子目录下
    selectedFile = new File(subDir, selectedFile.getName());
}
TFile archiveFile = new TFile(selectedFile + ".zip");

方案3:修改TrueZip配置(不推荐,版本兼容性差)

部分旧版本的TrueZip支持通过配置禁用根目录保护,但这个方法对版本依赖极强,且可能带来安全风险。如果一定要尝试,可以在代码开头添加:

import de.schlichtherle.truezip.fs.FsConfig;

// 禁用根目录归档检测限制
FsConfig.get().setArchiveDetector(FsConfig.get().getArchiveDetector().with(null));

注意:该方法在新版本TrueZip中可能已经失效,优先推荐前两个方案。


你提供的原始代码:

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileOutputStream;
import de.schlichtherle.truezip.zip.ZipEntry;
import de.schlichtherle.truezip.zip.ZipOutputStream;
import javax.swing.*;
import java.io.*;
public class MainClass {
    public static void main(String[] args) throws IOException {
        JFileChooser chooser = new JFileChooser();
        chooser.setDialogTitle("Please select the target folder.");
        chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
        JFrame applicationFrame = new JFrame();
        if (chooser.showSaveDialog(applicationFrame) != JFileChooser.APPROVE_OPTION) return;
        File selectedFile = chooser.getSelectedFile();
        TFile archiveFile = new TFile(selectedFile + ".zip");
        System.out.println("Selected file: " + archiveFile.getAbsolutePath());
        ZipOutputStream zipOutputStream = new ZipOutputStream(new TFileOutputStream(archiveFile));
        File folderToZip = new File("D:/filesToZip");
        File[] files = folderToZip.listFiles();
        for (File file : files) {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            int avail = bis.available();
            byte[] buffer = new byte[avail];
            if (avail > 0) {
                bis.read(buffer, 0, avail);
            }
            bis.close();
            ZipEntry zipEntry = new ZipEntry(file.getName());
            zipOutputStream.putNextEntry(zipEntry);
            zipOutputStream.write(buffer, 0, buffer.length);
            zipOutputStream.closeEntry();
        }
        zipOutputStream.close();
        System.exit(0);
    }
}

你遇到的错误信息:

Selected file: D:\test.zip
Exception in thread "main" java.io.FileNotFoundException: D:\test.zip
at de.schlichtherle.truezip.file.TFileOutputStream.newOutputStream(TFileOutputStream.java:147)
at de.schlichtherle.truezip.file.TFileOutputStream.(TFileOutputStream.java:116)
at MainClass.main(MainClass.java:21)
Caused by: de.schlichtherle.truezip.fs.FsArchiveFileSystemException: (only files can get replaced)
at de.schlichtherle.truezip.fs.FsArchiveFileSystem.mknod(FsArchiveFileSystem.java:379)
at de.schlichtherle.truezip.fs.FsBasicArchiveController$1Output.mknod(FsBasicArchiveController.java:273)
at de.schlichtherle.truezip.fs.FsBasicArchiveController$1Output.newOutputStream(FsBasicArchiveController.java:233)
at de.schlichtherle.truezip.fs.FsContextController$Output.newOutputStream(FsContextController.java:322)
at de.schlichtherle.truezip.fs.FsResourceController$Output.newOutputStream(FsResourceController.java:283)
at de.schlichtherle.truezip.socket.DelegatingOutputSocket.newOutputStream(DelegatingOutputSocket.java:57)
at de.schlichtherle.truezip.fs.FsSyncController$Output.newOutputStream(FsSyncController.java:454)
at de.schlichtherle.truezip.fs.FsLockController$Output$1NewOutputStream.call(FsLockController.java:509)
at de.schlichtherle.truezip.fs.FsLockController$Output$1NewOutputStream.call(FsLockController.java:506)
at de.schlichtherle.truezip.fs.FsLockController.locked(FsLockController.java:328)
at de.schlichtherle.truezip.fs.FsLockController.writeLocked(FsLockController.java:268)
at de.schlichtherle.truezip.fs.FsLockController$Output.newOutputStream(FsLockController.java:513)
at de.schlichtherle.truezip.fs.FsFinalizeController$Output.newOutputStream(FsFinalizeController.java:209)
at de.schlichtherle.truezip.fs.FsFalsePositiveArchiveController$1Output$NewOutputStream.call(FsFalsePositiveArchiveController.java:409)
at de.schlichtherle.truezip.fs.FsFalsePositiveArchiveController$1Output$NewOutputStream.call(FsFalsePositiveArchiveController.java:402)
at de.schlichtherle.truezip.fs.FsFalsePositiveArchiveController$TryChild.call(FsFalsePositiveArchiveController.java:507)
at de.schlichtherle.truezip.fs.FsFalsePositiveArchiveController.call(FsFalsePositiveArchiveController.java:104)
at de.schlichtherle.truezip.fs.FsFalsePositiveArchiveController$1Output.newOutputStream(FsFalsePositiveArchiveController.java:399)
at de.schlichtherle.truezip.file.TFileOutputStream.newOutputStream(TFileOutputStream.java:143)
... 2 more

内容的提问来源于stack exchange,提问作者fukiburi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:51:01