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

Posted

技术标签:

【中文标题】关闭并重新启动可执行文件后,无法修改或删除由我的 .jar 可执行文件创建的文本文件【英文标题】:Unable to modify or delete text file created by my .jar executable after closing and relaunching the executable 【发布时间】:2022-01-14 10:12:59 【问题描述】:

我有一个相当简单的 Java 项目,它在 当前目录(我的 Documents 文件夹中的某个位置)中打开(如果不存在则创建)一个文本文件,读取使用 BufferedReader 的数据,然后使用 PrintWriter 进行修改。该代码在 Eclipse 中运行良好。但是,当导出到可运行的 .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)
    ...

所以重申一下:

    在 Eclipse 中运行 - 工作正常 导出到可运行的 jar 运行罐子 如果文件不存在,则创建一个 读取文件 如果它在步骤 4 中创建了文件 - 写入成功,但如果文件已经存在 - 异常

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

磁盘 C 上的受限目录(这对我来说不可能,因为我的文件夹是 Documents 中一个完全可访问(至少一次)的文件夹,并且该文件夹的权限似乎是有序的) 忘记关闭流(我在 finally 块中关闭了读取器和写入器流,并确保它们已通过一些控制台打印行关闭) 正在使用文件(在计算机重新启动后问题仍然存在,即使在我之前必须重新安装操作系统之后) 缺少管理员权限(我以管理员身份启动 CMD 并使用它来“java -jar project.jar”,结果相同) 尝试使用等于 false 的 file.delete() 删除文件 尝试刷新打印写入器 尝试使用 file.setReadable(true) 和 file.setWritable(true) 将文件设置为可读可写

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

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

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;
    


这似乎不是代码的问题,但可能是我的系统的问题?

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

【问题讨论】:

您使用的是哪个操作系统?这段代码充斥着糟糕的代码风格问题。使用 replaceAll where replace(它也替换所有 - 区别是正则表达式)就足够了,可悲的异常处理,很多行什么都不做(所有那些 file.exists() 调用),不使用 ARM 块,等等 - 可能所有这些谷壳引起了一些问题;这确实让人很难通读。 没有理由首先调用createNewFile - 这不是它的用途(它是为了在两个不同的进程之间进行一些原始同步)。 new PrintWriter(file) 将根据需要制作文件。 @rzwitserloot Windows 10。过去的代码看起来不同,这些是试图根除我的异常原因的伤痕。就像我说的代码在 Eclipse 中运行良好,当我移动到导出的 jar 时,它的行为不再相同。 @rzwitserloot 谢谢,一旦我恢复理智,我会修改它。自 10 月以来,我一直被这个问题困扰。 使用Files.delete(file.toPath()) 可能会告诉您有关删除问题的更多信息,并检查任务管理器以查看是否存在相同应用程序的延迟版本。 【参考方案1】:

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

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

【讨论】:

以上是关于关闭并重新启动可执行文件后,无法修改或删除由我的 .jar 可执行文件创建的文本文件的主要内容,如果未能解决你的问题,请参考以下文章

python 持久的监督观察员。当看门狗重新启动时,检查自上次启动以来是否有新/修改/删除/等文件或目录,并发送

如何保护一个程序执行,不被任何打断或改变?

重新启动IoT设备并关闭自动更新

急!!!删除用户账户后无法登陆怎么办

Hbase无法正常启动,hbase网页打不开,HMaster启动后自动关闭

python 生成exe 打开后再关闭不能删除?