Java中的FileNotFoundException,即使文件存在也会出现

huangapple go评论78阅读模式
英文:

Java FileNotFoundException even if the file exists

问题

我正在构建一个应用程序,在其中我需要将包含用户信息的 HashMap<Integer, User> 存储到文件中。每当程序启动时,如果 users 文件不存在,它将创建一个新的空文件,当新用户注册时,我调用函数 saveUsers()HashMap 保存到文件中。当用户想要登录时,我调用函数 loadUsers() 从文件中读取并将对象存储在名为 usersHashMap 中。问题是,无论何时我调用 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&lt;Integer, User&gt; 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&lt;Integer, User&gt;) 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 = &quot;C:\\Users\\Me\\Desktop\\users.dat&quot;

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.&lt;init&gt;(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&lt;Integer, User&gt;) s.readObject();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

And got this error :

&gt; at index 33: C:\Users\Me\Desktop\users.dat &lt;

    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(&quot;C:\\Users\\Foo\\Bar&quot;);

答案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&lt;Integer, User&gt;) s.readObject();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

Even if this still fails, it might provide a different error, like "access denied".

huangapple
  • 本文由 发表于 2020年4月6日 07:40:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/61050931.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定