英文:
Java FileNotFoundException even if the file exists
问题
我正在构建一个应用程序,在其中我需要将包含用户信息的 HashMap<Integer, User>
存储到文件中。每当程序启动时,如果 users
文件不存在,它将创建一个新的空文件,当新用户注册时,我调用函数 saveUsers()
将 HashMap
保存到文件中。当用户想要登录时,我调用函数 loadUsers()
从文件中读取并将对象存储在名为 users
的 HashMap
中。问题是,无论何时我调用 loadUsers()
,程序总是抛出 FileNotFoundException
,即使文件存在,而且使用的是绝对路径。
以下是我的函数:
public void saveUsers() throws IOException {
File file = new File(usersFile);
FileOutputStream f = new FileOutputStream(file);
ObjectOutputStream s = new ObjectOutputStream(f);
s.writeObject(users);
s.close();
}
public void loadUsers() throws IOException {
File file = new File(usersFile);
// System.out.println(file.exists()); 总是返回 false
// System.out.println(file.getAbsolutePath().exists()); 总是返回 false
FileInputStream f = new FileInputStream(file);
ObjectInputStream s = new ObjectInputStream(f);
try {
users = (HashMap<Integer, User>) s.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
s.close();
}
在登录函数内部:
try {
loadUsers();
} catch (IOException e) {
System.out.println(e);
// 在这里我总是得到这个错误:
// java.io.FileNotFoundException: C:\Users\Me\Desktop\users.dat
// (The filename, directory name, or volume label syntax is incorrect)
}
Users
类是可序列化的,而且 usersFile = "C:\\Users\\Me\\Desktop\\users.dat"
我尝试使用 file:///
在开头,正斜杠和反斜杠,但似乎都不起作用。
当我在命令提示符中运行 dir C:\Users\Me\Desktop\users.dat
时,我得到以下结果:
Directory of C:\Users\Me\Desktop\users.dat
06/04/2020 01:03 616 users.dat
1 File(s) 616 bytes
0 Dir(s) 54,714,023,936 bytes free
异常和堆栈跟踪:
java.io.FileNotFoundException: C:\Users\Me\Desktop\users.dat
(The filename, directory name, or volume label syntax is incorrect)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at com.APP.loadUsers(APP.java:710)
at com.APP.login(APP.java:722)
at com.APP.lambda$6(APP.java:221)
编辑:
我尝试了以下代码:
public void loadUsers() throws IOException {
try (ObjectInputStream s = new
ObjectInputStream(Files.newInputStream(Paths.get(usersFile)))) {
try {
users = (HashMap<Integer, User>) s.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
但是得到了以下错误:
> at index 33: C:\Users\Me\Desktop\users.dat <
at sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
at sun.nio.fs.WindowsPath.parse(WindowsPath.java:94)
at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:255)
at java.nio.file.Paths.get(Paths.java:84)
英文:
I'm building an app where I need to store a HashMap<Integer, User>
containing users' information into a file. Whenever the program starts, if users
file doesn't exist it will create a new empty file, and whenever a new user registers I call the function saveUsers()
which saves the HashMap
into the file. When a user wants to login, I call the function loadUsers()
which reads the file and store the object in the HashMap
named users
. The problem is that the program always throw a FileNotFoundException
whenever I call loadUsers()
even if the file exists, and using the absolute path.
Here are my functions :
public void saveUsers() throws IOException {
File file = new File(usersFile);
FileOutputStream f = new FileOutputStream(file);
ObjectOutputStream s = new ObjectOutputStream(f);
s.writeObject(users);
s.close();
}
public void loadUsers() throws IOException {
File file = new File(usersFile);
//System.out.println(file.exists()); always returns false
//System.out.println(file.getAbsolutePath().exists()); always returns false
FileInputStream f = new FileInputStream(file);
ObjectInputStream s = new ObjectInputStream(f);
try {
users = (HashMap<Integer, User>) s.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
s.close();
}
Inside the login function :
try {
loadUsers();
} catch (IOException e) {
System.out.println(e);
// Here I always get this :
// java.io.FileNotFoundException: C:\Users\Me\Desktop\users.dat
// (The filename, directory name, or volume label syntax is incorrect)
}
The Users
class is Serializable and usersFile = "C:\\Users\\Me\\Desktop\\users.dat"
I tried using file:///
at the beginning, forward slashes and backslashes but nothing seems to work.
When I run dir C:\Users\Me\Desktop\users.dat
in command prompt I get this :
Directory of C:\Users\Me\Desktop\users.dat
06/04/2020 01:03 616 users.dat
1 File(s) 616 bytes
0 Dir(s) 54,714,023,936 bytes free
Exception and stack trace :
java.io.FileNotFoundException: C:\Users\Me\Desktop\users.dat
(The filename, directory name, or volume label syntax is incorrect)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at com.APP.loadUsers(APP.java:710)
at com.APP.login(APP.java:722)
at com.APP.lambda$6(APP.java:221)
Edit :
I tried this :
public void loadUsers() throws IOException {
try (ObjectInputStream s = new
ObjectInputStream(Files.newInputStream(Paths.get(usersFile)))) {
try {
users = (HashMap<Integer, User>) s.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
And got this error :
> at index 33: C:\Users\Me\Desktop\users.dat <
at sun.nio.fs.WindowsPathParser.normalize(WindowsPathParser.java:182)
at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:153)
at sun.nio.fs.WindowsPathParser.parse(WindowsPathParser.java:77)
at sun.nio.fs.WindowsPath.parse(WindowsPath.java:94)
at sun.nio.fs.WindowsFileSystem.getPath(WindowsFileSystem.java:255)
at java.nio.file.Paths.get(Paths.java:84)
答案1
得分: 4
错误强烈暗示该字符串中存在某种unicode字符。我建议您删除整行内容,然后手动重新输入,以避免此问题。
或者,也许您为了提问的目的而“清理”了那个名称,如果是这样的话:您的名称中是否有特殊字符(不是ASCII范围内的字符?)- 那么这很可能是问题所在。
您不需要在此之前放置file://
;对于这种代码风格,正确的方式是:File file = new File(“C:\\Users\\Foo\\Bar”);
英文:
The error strongly suggests there is a unicode character of some sort in that string. I suggest you delete the entire line and type it back in by hand to avoid this.
Alternatively, perhaps you 'cleaned' that name for the purposes of asking the question, in which case: Is there a fancy character in your name (something not from the ASCII range?) – then that's likely the problem.
You don't and shouldn't put file://
in front of this; the right way for this style of code is: File file = new File("C:\\Users\\Foo\\Bar");
答案2
得分: 1
老旧的Java文件I/O API以生成误导性的错误消息而闻名。使用在Java 7中添加的更新的NIO.2 API。
你还应该使用在Java 7中添加的try-with-resources。除非你被困在古老的Java 6或更早版本上,否则没有充分的理由不使用更新的API。
这将使你的代码看起来像这样:
public void loadUsers() throws IOException {
try (ObjectInputStream s = new ObjectInputStream(Files.newInputStream(Paths.get(usersFile)))) {
try {
users = (HashMap<Integer, User>) s.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
即使这仍然失败,它可能会提供一个不同的错误,比如“拒绝访问”。
英文:
The old Java File I/O API is notorious for generating misleading error messages. Use the newer NIO.2 API, which was added in Java 7.
You should also use try-with-resources, also added in Java 7. Unless you're stuck on ancient Java 6 or earlier, there is no good excuse for not using the newer APIs.
That would make your code look like this:
public void loadUsers() throws IOException {
try (ObjectInputStream s = new ObjectInputStream(Files.newInputStream(Paths.get(usersFile)))) {
try {
users = (HashMap<Integer, User>) s.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Even if this still fails, it might provide a different error, like "access denied".
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论