在 Java 中使用 apache commons vfs2 访问后删除 zip 文件

Deleting zip file after accessing with apache commons vfs2 in Java

我正在尝试使用 apache commons vfs2 来读取 zip 文件的内容,就好像它只是另一个目录一样。 zip 文件最终将包含所有类型的文件(甚至可能是一个小型数据库)。

出于说明目的,我创建了一些 zip 文件,其中包含一个名为 project.json 的文件,该文件是 json 用于具有名称和描述的项目。当我得到zip文件时,我想读取json文件以从中获取项目定义信息等。

这一切都很好。现在,我希望我的用户能够从应用程序中删除这些文件。这就是我不满意的地方。

认为 我关闭了所有输入流等,但是应用程序中的文件似乎被锁定,不允许我删除它。

如果您想创建自己的 zip 文件来尝试,这里有一个简单的 json 字符串。

{"project": {"name": "ProjectX", "description": "X is a project."}}

将其复制到名为 project.json 的文件中并保存。然后,将其压缩到 Java 项目根目录中的一个 zip 文件中。

下面的例子说明了我的困境:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.VFS;
import org.json.JSONObject;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.stage.Stage;

public class FileLockExample extends Application {

    @Override
    public void start(Stage arg0) throws Exception {
        ObservableList<File> files = retrieveFiles();
        deleteFiles(files);
        Platform.exit();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }

    public ObservableList<File> retrieveFiles() {
        File[] files = new File(".").listFiles(new FilenameFilter() { 
            @Override 
            public boolean accept(File dir, String name) { 
                return name.endsWith(".zip");
            }
        });
        for (File file : files) {
            try {
                FileSystemManager fsManager = VFS.getManager();
                FileObject zipFile = fsManager.resolveFile("zip:" + file.toURI());
                FileObject projectJson = fsManager.resolveFile(zipFile, "project.json");
                FileContent content = projectJson.getContent();

                InputStream in = content.getInputStream();
                byte[] buffer = new byte[1024];
                StringBuilder sb = new StringBuilder();
                int len;
                while ((len = in.read(buffer)) > 0) {
                    sb.append(new String(buffer, 0, len));
                }
                in.close();
                String json = sb.toString();

                JSONObject obj = new JSONObject(json);
                String name = obj.getJSONObject("project").getString("name");
                String description = obj.getJSONObject("project").getString("description");
                System.out.println("Found project : " + name + "(" + description + ")");
                content.close();
                projectJson.close();
                zipFile.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return FXCollections.observableArrayList(files);
    }

    public void deleteFiles(ObservableList<File> files) {
        for (File file : files) {
            System.out.println("Deleting " + file.getName());
            file.deleteOnExit();
        }
    }
}

鉴于似乎没有人对我的问题感兴趣,这让我开始反思在这种情况下使用 Apache Commons VFS。我决定探索其他选择,并且能够通过使用 java.nio API 来实现我的短期目标。现在,我们的长期目标是尝试在 zip 文件中存储其他类型的文件,并以随机方式访问它们。

万一有人关心,这里是我的示例代码,用于从文件系统中读取和删除 zip 文件,而无需求助于 InputStreamOutputStream

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.nio.file.spi.FileSystemProvider;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONObject;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.stage.Stage;

public class FileLockExample extends Application {

    @Override
    public void start(Stage arg0) throws Exception {
        ObservableList<File> files = retrieveFiles();
        deleteFiles(files);
        Platform.exit();
    }

    public static void main(String[] args) {
        Application.launch(args);
    }

    public ObservableList<File> retrieveFiles() {
        File[] files = new File(".").listFiles(new FilenameFilter() { 
            @Override 
            public boolean accept(File dir, String name) { 
                return name.endsWith(".zip");
            }
        });
        for (File file : files) {
            try {
                Map<String, Object> env = new HashMap<>();
                FileSystemProvider provider = getZipFSProvider();
                URI uri = new URI("jar:" + file.toURI());
                FileSystem zipfs = provider.newFileSystem(uri, env);
                List<String> jsonList = Files.readAllLines(zipfs.getPath("/project.json"));
                StringBuilder sb = new StringBuilder();
                for (String string : jsonList) {
                    sb.append(string);
                }
                String json = sb.toString();
                JSONObject obj = new JSONObject(json);
                String name = obj.getJSONObject("project").getString("name");
                String description = obj.getJSONObject("project").getString("description");
                System.out.println("Found project : " + name + " (" + description + ")");
            } catch (URISyntaxException use) {
                use.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return FXCollections.observableArrayList(files);
    }

    public void deleteFiles(ObservableList<File> files) {
        for (File file : files) {
            System.out.println("Deleting " + file.getName());
            file.deleteOnExit();
        }
    }

    private static FileSystemProvider getZipFSProvider() {
        for (FileSystemProvider provider : FileSystemProvider.installedProviders()) {
            if ("jar".equals(provider.getScheme()))
                return provider;
        }
        return null;
    }

}