简体   繁体   中英

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

the code that i used:

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();
        
    }
    
    
    
}

the line below int he above code:

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

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

if i copy this directly and put it in the chrome's url putting box. the file opens but the line:

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

gives file not found error.

error stack:

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)

thankyou for the help.

The file: bit makes what you see not actually a file path, but a URL.

URL has the toFile() method which is closer to what you want, but still isn't what you're actually looking for, which is getResourceAsStream :

  1. The appropriate way to call getResource / getResourceAsStream , is Play.class.getResource , not getClass().getResource . A minor nit; the getClass() variant is non-idiomatic, and strictly worse/less readable: If Play is ever subclassed, it breaks, whereas Play.class.getResource would not. Even if it isn't relevant, better to use the style that is more idiomatic and the right answer is strictly more scenarios.

  2. Generally, if you convert the resource you get into a file you've messed up; the point of getResource is to give you resources from the same place your classes are found, and they need not be files . They could be entries in a jar (which aren't, themselves, files, and cannot be accessed directly either as a java.io.File or as a java.nio.path.Path ), pulled in over the network, generated on the fly - anything goes, that's the point of the abstraction. In this case, you're taking your file and immediately turning that into an InputStream . Don't do that - the getResource abstraction can do this.

  3. Like all resources, you can't just open an inputstream like this. You need to ensure it is closed as well, regardless of what happens. Use try-with-resources to ensure this.

Putting it all together:

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

No need to close it; the try construct will take care of it for you. Doesn't matter how code 'exits' those braces (by running to the end of it, via return or some other control flow, or via an exception) - that inputstream will be closed.

You can use the File constructor File(URI uri) transforming your URL url to URI and passing it as an argument for the File constructor like below:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM