简体   繁体   中英

How to place a file for jar and read it with FileInputStream

This is the code

public static void readCharacters() {

    try (FileInputStream fi = new FileInputStream("main/characters.dat"); ObjectInputStream os = new ObjectInputStream(fi)) {

        characterList = (LinkedList<Character>) os.readObject();

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

This is the structure: 在此处输入图片说明

And this is the Error

java.io.FileNotFoundException: main\\characters.dat (The system cannot find the path specified)

What I want is to include the characters.dat file in my jar, and be able to read and write it while the program runs. Is there a different way to write the path? or to put the .dat file in a different position.

Also the writing method:

public static void writeCharacters() {
    try (FileOutputStream fs = new FileOutputStream("main/characters.dat"); ObjectOutputStream os = new ObjectOutputStream(fs)) {
        System.out.println("Writing Characters...");
        os.writeObject(characterList);

    } catch (FileNotFoundException e) {

        e.printStackTrace();
    } catch (IOException e) {

        e.printStackTrace();
    }

}

You can't. You can do one or the other. JAR files are not file systems, and their entries are not files. You can read it with an input stream:

InputStream in = this.getClass().getResourceAsStream("/main/characters.dat");

Check it for null before proceeding.

The jar is for read-only resources. You can use it for the initial file, as a kind of template.

Path path = Paths.get(System.getProperty("user.home") + "/myapp/chars.dat");
Files.mkdirs(path.getParentPath());
if (!Files.exists()) {
    try (InputStream in =
            Controller.class.getResourceAsStream("/main/characters.dat")) {
         Files.copy(in, path);
    }
}

The above copies the initial.dat resource from the jar to the user's home "myapp" directory, which is a common solution.

System.getProperty("user.dir") would the running directory. One can also take the jar's path:

URL url = Controller.class.getResource("/main/characters.dat");
String s = url.toExternalForm(); // "jar:file:/.... /xxx.jar!/main/characters.dat"

From that you can also construct the jar's directory. Mind to check Windows, Linux, spaces and such.

URL url = Controller.class.getProtectionDomain().getCodeSource().getLocation();

The solution above risks a NullPointerException, and works a bit differenly running inside the IDE or stand-alone.

Important note:

When using getResourceAsStream , you must start your path by slash / , this specifies the root of your jar, .getResourceAsStream("/file.txt");

In my case my file was a function argument, String filename , I had to do it like this:

InputStream in = this.getClass().getResourceAsStream("/" + filename);

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