0

I have written a project where some images are used for the application's appearance and some text files will get created and deleted along the process. I only used the absolute path of all used files in order to see how the project would work, and now that it is finished I want to send it to someone else. so what I'm asking for is that how I can link those files to the project so that the other person doesn't have to set those absolute paths relative to their computer. something like, turning the final jar file with necessary files into a zip file and then that the person extracts the zip file and imports jar file, when runs it, the program work without any problems. by the way, I add the images using ImageIcon class.

I'm using eclipse.

Navid Nasro
  • 19
  • 1
  • 6
  • Better to load your files/images as [resources (Netbeans)](https://technojeeves.com/index.php/aliasjava1/78-loading-files-as-resources-in-java-with-netbeans) and [Eclipse](https://technojeeves.com/index.php/aliasjava1/80-loading-files-as-resources-in-java-with-eclipse) where they are read-only. You could leave the writable paths as relative to the current directory (On clipboard) – g00se Jul 23 '21 at 17:33
  • @g00se could you please explain more with examples? – Navid Nasro Jul 23 '21 at 17:54
  • Looks like I don't need to with the answer below. The only thing i'd say is for your main resource 'folders' (they are not folders in the file system sense once your app is deployed) you should start your addressing with `/` from each resource root, e.g. `/img`,`/data` etc. – g00se Jul 23 '21 at 18:40

1 Answers1

0

For files that you just want to read, such as images used in your app's icons:

  • Ship them the same way you ship your class files: In your jar or jmod file.
  • Use YourClassName.class.getResource or .getResourceAsStream to read these. They are not files, any APIs that need a File object can't work. Don't use those APIs (they are bad) - good APIs take a URI, URL, or InputStream, which works fine with this.

Example:

package com.foo;

public class MyMainApp {

    public void example() {
        Image image = new Image(MyMainApp.class.getResource("img/send.png");
    }

    public void example2() throws IOException {
        try (var raw = MyMainApp.class.getResourceAsStream("/data/countries.txt")) {
            BufferedReader in = new BufferedReader(
              new InputStreamReader(raw, StandardCharsets.UTF_8));
            for (String line = in.readLine(); line != null; line = in.readLine()) {
              // do something with each country
            }
        }
    }
}

This class file will end up in your jar as /com/foo/MyMainApp.class. That same jar file should also contain /com/foo/img/send.png and /data/countries.txt. (Note how starting the string argument you pass to getResource(AsStream) can start with a slash or not, which controls whether it's relative to the location of the class or to the root of the jar. Your choice as to what you find nicer).

For files that your app will create / update:

  • This shouldn't be anywhere near where your jar file is. That's late 80s/silly windows thinking. Applications are (or should be!) in places that you that that app cannot write to. In general the installation directory of an application is a read-only affair, and most certainly should not be containing a user's documents. These should be in the 'user home' or possibly in e.g. `My Documents'.

Example:

public void save() throws IOException {
    Path p = Paths.get(System.getProperty("user.home"), "navids-app.save");
    // save to that file.
}
rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • thanks for your great explanation.so if i make these changes like you said for images MyMainApp.class.getResource("img/TheNameOfImage.png") and for reading from files MyMainApp.class.getResourceAsStream("/data/TheNameOfTheFile.txt") and for writing to the files System.getProperty("user.home") then the problem is solved right? – Navid Nasro Jul 23 '21 at 19:27
  • by the way what should be passed as arguments to System.getProperty() in my case? – Navid Nasro Jul 23 '21 at 19:29
  • `"user.home"`. Literally. That's java-ese for: "Get me the user's home dir". It's `/Users/foobar` on a mac, for example. – rzwitserloot Jul 23 '21 at 20:38
  • fine,i'm trying to create a file this way but unfortunately, it throws an IOexception would you please look at my code?`Formatter writer=new Formatter(new FileWriter(new File(System.getProperty("user.dir", "Records.txt")),true))` here i'm creating a file to the user's home directory and that Records.txt is the name of the file I want to create. – Navid Nasro Jul 24 '21 at 12:38
  • also an IOexception gets thrown when i want to read from a txt file `Scanner scan=new Scanner(SearchRecordPage.class.getResourceAsStream("/data/Records.txt"))` what am i doing wrong? – Navid Nasro Jul 24 '21 at 12:43
  • `System.getProperty("user.dir", "Records.txt")` this call means: Get the property `user.dir`. If that does not exist, return the string `Records.txt` instead. A bug, in other words - pay attention to your braces and learn how to debug. You wanted `new File(System.getProperty("user.dir"), "Records.txt")` - note the location of the parens. Also, FileWriter is probably not what you wanted, it uses platform default encoding, which is a funny way of saying 'never what you want'. Just use the new files API (`java.nio.file.Files`, and `Path`), they default to sane thing (UTF-8), have a nicer API too. – rzwitserloot Jul 24 '21 at 13:05
  • Comments aren't a good place to ask unrelated follow questions, especially because questions require stack traces and error prints and comments aren't good places to put those. Ask new questions on SO if they confuse you, but try to spend 5 minutes debugging it first. – rzwitserloot Jul 24 '21 at 13:06
  • yeah, I appreciate that.I posted another topic-related question. would you please check that one out?[link](https://stackoverflow.com/questions/68518431/creating-a-text-file-with-java-without-using-absolute-path) – Navid Nasro Jul 25 '21 at 12:14