关闭并重新启动可执行文件后,无法修改或删除由我的 .jar 可执行文件创建的文本文件

Unable to modify or delete text file created by my .jar executable after closing and relaunching the executable

我有一个相当简单的 Java 项目,它打开(如果不存在则创建)当前目录(我的 [=31 中某处)中的文本文件=]Documents文件夹),用BufferedReader读取数据,然后用PrintWriter修改。该代码在 Eclipse 中运行良好。但是当导出到 运行nable .jar 文件时,生成的 .jar 可执行文件只能修改它自己创建的文件(创建是因为它之前不存在)。如果我然后关闭并重新启动 .jar 作为新实例来修改它上次启动时创建的文件,我得到

java.io.FileNotFoundException: Data.txt (Access is denied)
    at java.base/java.io.FileOutputStream.open0(Native Method)
    at java.base/java.io.FileOutputStream.open(FileOutputStream.java:293)
    at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:235)
    at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:184)
    at java.base/java.io.PrintWriter.<init>(PrintWriter.java:309)
    at project.file.LocalStorageFile.setList(LocalStorageFile.java:136)
    ...

所以重申一下:

  1. 运行 在 eclipse 中 - 工作正常
  2. 导出到运行可用的 jar
  3. 运行罐子
  4. 如果文件不存在则创建一个
  5. 读取文件
  6. 如果它在第 4 步中创建了文件 - 写入成功,但如果文件已经存在 - 异常

在调查此异常时,答案建议:

我正在使用 gradle 构建我的 .jar,因为我需要一些从那里获取的库来实现其他功能。但即使我使用 Eclipse 本身“导出为 运行nable jar”,我也会遇到同样的问题。当然,当我多次直接从 Eclipse 运行 程序时,访问和修改同一个文件没有问题。

这是我的 LocalStorageFile class,如果你想在你的机器上测试它,它具有读写功能:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.TreeMap;

/**
 * Store keywords and strings in a local file.
 * 
 * Format: keyword1, keyword2 \t string1 \n keyword3, keyword4 \t string2
 * \n
 */
public class LocalStorageFile {
    private static final String FILE_PATH = "Data.txt"; // current directory
    private static final String KEY_SEP = "\t"; // key/value separator
    private static final String LINE_SEP = "\n"; // line separator

    private static File file;

    public LocalStorageFile() {
        file = new File(FILE_PATH);

        // Create file if it doesn't exist
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Retrieve list from file "Data.txt" in local directory.
     * 
     * @return TreeMap of keys and strings.
     */
    public static TreeMap<String, String> getList() {
        System.out.println("Retrieving list data.");
        TreeMap<String, String> myList = new TreeMap<String, String>();

        File file = new File(FILE_PATH);
        if (!file.exists()) {
            try {
                file.createNewFile(); // if file already exists will do nothing
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }

        BufferedReader br = null;
        // Read file line by line and add to myList
        try {
            file.setReadable(true);
            file.setWritable(true);
            br = new BufferedReader(new FileReader(file));
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println("  Now reading line:" + line);
                String[] keyValuePair = line.split(KEY_SEP);
                if (keyValuePair.length == 2) { // avoid any error lines
                    // Re-insert tabs and newlines
                    String key = keyValuePair[0].replaceAll("\\t", "\t")
                            .replaceAll("\\n", "\n");
                    String value = keyValuePair[1].replaceAll("\\t", "\t")
                            .replaceAll("\\n", "\n");
                    // Put data into map
                    myList.put(key, value);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (br != null) {
                    br.close();
                    System.out.println("Buffered reader closed.");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return myList;
    }

    /**
     * Rewrite list to file "Data.txt" in local directory.
     * 
     * @param myList
     *            TreeMap of keys and strings.
     * @return 1 on success, 0 on fail.
     */
    public static int setList(TreeMap<String, String> myList) {
        System.out.println("Saving list data.");
        String textData = "";
        int result = 0;

        // Construct textData using myList
        for (String key : myList.keySet()) {
            String value = myList.get(key);

            // Sanitize strings
            String keyClean = key.replaceAll("\t", "\\t").replaceAll("\n",
                    "\\n");
            String valueClean = value.replaceAll("\t", "\\t").replaceAll(
                    "\n", "\\n");

            // Assemble line with separators
            String line = keyClean + KEY_SEP + valueClean + LINE_SEP;

            System.out.println("  Now saving line:" + line);
            textData += line;
        }

        // Replace file content with textData
        PrintWriter prw = null;
        File file = new File(FILE_PATH);
        if (file.exists()) {
            boolean delStatus = file.delete();
            System.out.println("File deleted? " + delStatus);
            // file.setReadable(true);
            // file.setWritable(true);
        } else {
            System.out.println("File doesn't exist");
        }
        try {
            file.createNewFile();

            prw = new PrintWriter(file); // <- this is line 136 from the exception
            prw.println(textData);
            prw.flush();
            result = 1;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (prw != null) {
                prw.close();
                System.out.println("Print writer closed.");
            }
        }
        return result;
    }

}

这似乎不是代码的问题,但也许我的系统有问题?

任何关于我应该在哪里挖掘的线索都将不胜感激。

好的。我终于开始工作了。我不得不暂时关闭我的 Avast Antivirus 并且我能够编辑现有文件。特别是“勒索软件保护”正在保护我的文档文件夹。

谢谢各位评论者的帮助,没有你们我不可能得出这个结论! 中的一个答案提到了导致同样问题的 Comodo 杀毒软件。我将在未受保护的文件夹中创建一个新的工作目录,因为 Avast 不允许我作为例外添加非 exe 文件。