关闭并重新启动可执行文件后,无法修改或删除由我的 .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 持久的监督观察员。当看门狗重新启动时,检查自上次启动以来是否有新/修改/删除/等文件或目录,并发送