java.io.FileNotFoundException 即使文件路径正确

java.io.FileNotFoundException even when the file path is correct

我使用的代码:

package play;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

public class Play {

    InputStream music;
    public Play() {
    URL url=getClass().getResource("/music/Whitewoods - College Kill Dream.mp3");
    System.out.println(url.toString());
    try {
        FileInputStream fileInputStream=new FileInputStream(new File(url.toString()));
        fileInputStream.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
        
    }
    public static void main(String args[]) {
        new Play();
        
    }
    
    
    
}

上面代码下面的行:

System.out.println(url.toString());

prints :
file:/C:/Users/eclipse-workspace/audioboard/bin/music/Whitewoods%20-%20College%20Kill%20Dream.mp3

如果我直接复制这个并把它放在 chrome 的 url 放置框里。文件打开但行:

FileInputStream fileInputStream=new FileInputStream(new File(url.toString()));

给出文件未找到错误。

错误堆栈:

java.io.FileNotFoundException: file:\C:\Users\eclipse-workspace\audioboard\bin\music\Whitewoods%20-%20College%20Kill%20Dream.mp3 (The filename, directory name, or volume label syntax is incorrect)
    at java.base/java.io.FileInputStream.open0(Native Method)
    at java.base/java.io.FileInputStream.open(FileInputStream.java:213)
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:155)
    at play.Play.<init>(Play.java:17)
    at play.Play.main(Play.java:26)

谢谢你的帮助。

file: 位使您看到的实际上不是文件路径,而是 URL.

URL 有 toFile() 方法,它更接近您想要的,但仍然不是您实际要寻找的方法,即 getResourceAsStream:

  1. 调用getResource/getResourceAsStream的合适方法是Play.class.getResource,而不是getClass().getResource。一个小尼特; getClass() 变体是非惯用的,并且严格地 worse/less 可读:如果 Play 曾经被子类化,它就会中断,而 Play.class.getResource 则不会。即使不相关,也最好使用更惯用的风格,正确答案严格来说是更多的场景。

  2. 通常,如果您将获得的资源转换为文件,您就会搞砸了; getResource 的要点是从找到 类 的同一位置为您提供资源,并且 它们不必是文件 。它们可以是 jar 中的条目(它们本身不是文件,并且不能作为 java.io.Filejava.nio.path.Path 直接访问),通过网络拉入,即时生成- 任何事情,这就是抽象的重点。在这种情况下,您正在获取文件并 立即 将其转换为 InputStream。不要那样做 - getResource 抽象可以做到这一点。

  3. 像所有资源一样,您不能像这样打开输入流。无论发生什么情况,您都需要确保它也已关闭。使用 try-with-resources 来确保这一点。

综合起来:

String songName = "Whitewoods - College Kill Dream.mp3";
try (var in = Play.class.getResourceAsStream("/music/" + songName)) {
   //  .... do something with 'in' here. It is an InputStream.
}

不需要关闭; try 构造将为您处理它。 'exits' 那些大括号的代码(通过 运行 结束,通过 return 或其他一些控制流,或通过异常)并不重要 - 输入流将被关闭。

您可以使用 File 构造函数 File(URI uri)URL url 转换为 URI 并将其作为参数传递给 File 构造函数如下:

File file = new File(url.toURI());