我正在构建一个应用程序,需要在其中将包含用户信息的HashMap<Integer, User>
存储到文件中。每当程序启动时,如果users
文件不存在,它将创建一个新的空文件,并且每当有新用户注册时,我都会调用函数saveUsers()
,该函数会将HashMap
保存到文件中。当用户想要登录时,我调用函数loadUsers()
来读取文件并将对象存储在名为HashMap
的users
中。问题在于,即使文件存在并使用绝对路径,只要我调用FileNotFoundException
,程序总是会抛出loadUsers()
。
这是我的职能:
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();
}
在登录功能内:
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)
}
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)
该错误强烈表明该字符串中存在某种Unicode字符。我建议您删除整行,然后手动键入以免出现这种情况。
或者,您可能是出于询问的目的而“清理”了该名称,在这种情况下:您的名称中是否有一个奇特的字符(不是ASCII范围内的字符?),这可能就是问题所在。
您不也不应在此前面加上file://
;这种代码风格的正确方法是:File file = new File("C:\\Users\\Foo\\Bar");
旧的Java File 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();
}
}
}
即使仍然失败,它也可能会提供其他错误,例如“访问被拒绝”。