13

I know that .jar files are basically archives as well as being applications. What I'm asking is how can I store data(actual files not just strings) packed inside my program? I want to do this within my Java code.

The reason for this if your wondering is that I'm producing a server mod of a game. The server starts and creates all the level data and I want to store all these file inside my .jar app.

liamzebedee
  • 14,010
  • 21
  • 72
  • 118

6 Answers6

19

Yes you can do this.

Non-code resources in a JAR file on the classpath can be accessed using Class.getResourceAsStream(String). Applications routinely do this, for example, to embed internationalized messages as resource bundles.

To get your file into the JAR file (at project build time!), just copy it into the appropriate place in the input directory tree before you run the jar command. Build tools such as Maven, Gradle, etc can automate that for you.


Is there a way to add files to the archive within the app?

In theory, your application could store files inside its own JAR file, under certain circumstances:

  • The JAR has to be a file in the local file system; i.e. not a JAR that was fetched from a remote server.
  • The application has to have write access to the JAR file and its parent directory.
  • The application must not need to read back the file it wrote to the JAR in the current classloader; i.e. without exiting and restarting.
  • The JAR must not need to be be signed.

The procedure would be:

  1. Locate the JAR file and open as a ZIP archive reader.
  2. Create a ZIP archive writer to write a new version of JAR file.
  3. Write the application's files to the writer.
  4. Write all resources from the ZIP reader to the writer, excluding old versions of the applications files.
  5. Close the reader and writer.
  6. Rename the new version of the JAR to replace the old one.

The last step might not work if the initial JAR is locked by the JVM / OS. In that case, you need do the renaming in a wrapper script.

However, I think that most people would agree that this is a BAD IDEA. It is simpler and more robust to just write regular files.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
4

The other answers have provided some good strategies, but I am going to suggest going in a somewhat different direction.

This game supposedly has graphics and is a desktop application. It is most easy to distribute desktop applications from a web server.

If both those things are true of your game, then look into using Java Web Start to deploy it.

JWS offers APIs not available to other apps. & one of particular interest to this problem is the PersistenceService. The PersistenceService allows for small amounts of data to be stored and restored by an app. (even when it is in a sand-box). I have made a small demo. of the PersistenceService.

The idea would be to check the PersistenceService for the application data, and if not found, use the data in the Jars. If the user/application alters the data, write the altered data to the PersistenceService.


JWS also offers other nice features like splash screens, desktop integration, automatic updates..

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • Is this JWS supposedly like embeding a flash file in a webpage? – liamzebedee Oct 30 '10 at 01:29
  • In a 1.6.0_10+ JRE, applets can be embedded into a web page and use the JWS services. OTOH from Java 1.2+, JWS could launch frames or applets as free-floating on the desktop. I have dabbled in the former (and can give you some examples) but have mostly used the latter (of which the JNLP API examples page I linked earlier is only a small sample). Even if developing an applet, I would recommend using the free-floating option - at least initially. – Andrew Thompson Oct 30 '10 at 04:20
1

By creating a file in the Source Packages (ex: /src/resource/file.txt) its contents can be read using Class.getResourceAsStream(String)

This is a working implementation of the following answer

    InputStream is = Class.class.getResourceAsStream("/resource/file.txt");        
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    StringBuilder sb = new StringBuilder();
    String line;
    while((line = br.readLine()) != null) {
        sb.append(line).append("\n");
    }
    System.out.println(sb.toString());
Community
  • 1
  • 1
user2601995
  • 6,463
  • 8
  • 37
  • 41
1

This is not possible. You however can look into embedded databases for your usecase. Java 6 comes with JavaDB. If you doesn't want to use it then you can find more here http://java-source.net/open-source/database-engines

Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
  • Well if you can add files through an archive program such as 7zip or WinRAR then why can't you do this inside an application? – liamzebedee Oct 30 '10 at 00:29
  • Because you need to have ability to write to the file system which is by default prohibited by security policy when running in a container. – Aravind Yarram Oct 30 '10 at 00:32
1

I would recommend that you consider having two JARs: one to store your application's class files and another JAR to store the user data. If you do not have two separate JARs, then you will have difficulties obtaining a write lock from the Operating System (since you would be trying to overwrite the JAR containing your program while java is reading it).

To create a JAR, use the java.util.jar.JarFile class. There is also another question on stackoverflow which describes how to create/write a JAR file.

Community
  • 1
  • 1
David-Zazeski
  • 254
  • 1
  • 2
1

Don't do this. A jar file is a source of application classes and resources, not a file system. You wouldn't try to save files into a exe, would you?

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 3
    Windows' standalone executables, and macOS' .app bundles disagree with you. It's perfectly sensible to want a a cohesive self contained bundle of all your applications guts. – Alexander Dec 04 '16 at 20:27
  • @Alexander They disagree how? A Windows standalone executable is read-only from the point of view of the application. – user207421 Sep 07 '18 at 11:17
  • 1
    Ah, interesting, nevermind then. My point is valid for `.app` bundles, though, which are just folders with a special icon and left click action. They're totally mutable, even though that's discouraged. – Alexander Sep 07 '18 at 16:25