So I have to figure out how to use a single .properties file across 7 different executable jar files that all eventually call one another in some way shape or form. I'm compiling with ant to a dist folder and I will put the properties file in that folder but I want to know if once I start the first program if it is possible to access the buffered properties file from the other 6 programs?
Properties properties = new Properties();
BufferedInputStream stream = new BufferedInputStream(new FileInputStream("example.properties"));
properties.load(stream);
stream.close();
String sprache = properties.getProperty("lang");
But I'm not sure how to access that same buffer from program 1 to program 2?
Edit: I guess I im hoping there is a way to share that buffer but in theory I could just load an instance of the properties file into each of the jar files.
If the programs run in separate VMs, you cannot access objects of one program from the other, unless you use some inter-process communications (IPC) functionality (shared cache, socket communication, etc.), but implementing such functionality is much more complex (and even slower) than simply re-reading the properties file in each program.
7 executable jars will share 7 different JVM processes when running, so the normal (or is that sane?) answer is: no. Now if you are willing to run a small server app, you could use RMI to synchronize between them. However, at that point you're starting to run into the question of why they're not EJBs running in a container where the resource can be shared.
Related
If I have a resource file (mydata.txt) in resources folder (set up as another source folder) of my application. This mydata.txt eventually would be packaged inside root of a jar file (.war) to be deployed to some application server (Tomcat, Jetty, WildFly).
File mydata.txt has some crucial data needed to the application, and this file shall be appended by the application.
To get a file from jar I can use getClass().getResourceAsStream("/mydata.txt") - thus I get this file as InputStream. But there is no way I can get this file as OutputStream and write to it.
All solutions with getClass().getResource() - returning URL are discouraged, getResourceAsStream is always recommended, but it allows only reading, not writing/updating/appending the file.
getClass().getProtectionDomain().getCodeSource() solution is also discouraged to get (write) access to the file.
I could create some file in a temporary directory on Tomcat Server (System.getProperty("java.io.tmpdir") and write to it, but it is nonsense because this file contents is crucial for the application (to write it to tmp dir), besides I need to append file, not create a new one and write to it.
Also, I am not sure that writing to any other directory (other than tmp) of application server is a good idea (please correct me if I am wrong here).
So I come to the conclusion that it is not recommended to save any data to a file in enterprise application, so I shall always use a database instead?
In short: Yes. Beside all you mentioned (which is all correct) the biggest problems are
concurrent access
transaction handling
which both a database serves perfect and with a file approach is just a pain in the ****
In addition to that especially an application server provides you with configuration of connection (and pools) to data sources of any kind, which is really handy in a production environment.
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.
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:
Locate the JAR file and open as a ZIP archive reader.
Create a ZIP archive writer to write a new version of JAR file.
Write the application's files to the writer.
Write all resources from the ZIP reader to the writer, excluding old versions of the applications files.
Close the reader and writer.
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.
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..
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
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.
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?
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());
This question already exists:
Does java FileChannnel.transferTo() work cleverly when files are on network?
Closed 7 years ago.
The code is written in Java 1.7
I want to make some major modifications to a binary file on a slow network.To protect against the network connection being lost instead of writing directly to the file I write to a new file. When I have completed writing to the new file I delete the old file and rename the new file to the old file.
My question is is it better for the new file to be
1. On the same location as the original file
2. Locally on the computer
With 1. writing to the file could be slower, but the rename should be quicker in fact with most oses would be immediate . With 2 writing to the file should be quicker but then renaming the filwe would be slower.
I feel the answer is 1.
Actually if I open a Filechannel to both files and transfer files directly from one channel to another do the bytes have to come from network to my computer and back to network or can they been copied directly from one place on network to the the ther.
I'm guessing here but the files are probably mounted via some network file system (NFS, SMB) on your computer. So you can access them like local files; they are just slower.
As for the first question: You're not gaining anything by first writing the file locally. In the end, you always have to move the file to correct place in the network and that always involves a "copy all bytes" operation. For example, Java's File.rename() will fail when the two files aren't on the same harddisk / mount. So you have to manually copy the bytes to the destination folder anyway. Some IO frameworks do that for you when necessary but it always happens.
As for directly copying data between two remote hosts: There are a few network filesystems which support such operations but it's a special feature. The usual culprits (NFS and SMB) don't. They always download the whole file from the source and then upload it to the target.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can a Java program use files inside the .jar for read and write?
I am in the process of creating a game, and I want it all to run from on runnable jar file, so all of my resources (images and text files) are going to be inside the jar file.
The problem that I'm having with this is that it is extremely difficult to deal with files inside the jar.
I am using eclipse, which can sometimes play tricks on you because it will find the files if you run it from eclipse, but if you export it won't.
I just want to know basically the proper way to dew a few things:
I need to be able to load images (which I have working, somehow. I sort of tinkered with it and did it on accident, so I have no clue how it works)
I need to be able to read from text files (I have this working too, again, by accident and hours of guessing.)
I need to be able to write to text files that exist and and are in the jar. This is what is making me think I'm doing it all wrong. All I want to do is be able to save certain settings so they work on the next load, and I have no clue how to write to the file.
In eclipse (Indigo) I made a folder names "resources" and marked it as a source folder. I put all of my images and text files in there.
I read in images like this:
public static Image ammo = new ImageIcon(TankMazeGame.class.getResource("ammo.png")).getImage();
I read text files like this:
InputStream is = TankMazeRunner.class.getClassLoader().getResourceAsStream("Settings.txt");
Scanner settingsReader = new Scanner(new InputStreamReader(is));
I am writing to my settings file like this, but it isn't really working, so that's what I need help with.
File settingsFile = new File(DisplayMenu.class.getClassLoader().getResource("Settings.txt").getFile());
try {
OutputStream os = new FileOutputStream(settingsFile, true);
PrintWriter pw = new PrintWriter(os, true);
pw.write("SIZE: " + TankMazeRunner.WIDTH + "\n");
os.flush();
pw.close();
} catch (Exception e2) {
System.out.println("Error");
}
As you can probably tell from my code, I'm lost.
For others who come across this question.
You cannot do this unless you can place constraints on the OS being used, and even then you may not be able to do this.
Here are some constraints to be aware of:
Microsoft Windows implements its own read-write lock symmantics: you cannot write to a file while there is a read handle open. The JVM will have a read handle open as the this is the file on the classpath, therefore not possible in Java (unless you want to fork a temporary process, kill yourself, let the temp process rewrite and relaunch... Which will be ugly and the anti-virus will likely stop the temp process anyway)
Most unix OS implementations will have no issue, though the JVM will have cached offsets within the JAR file, so your program will crash as soon as you are done and attempt to load a class.
only windows users tend not to use file permissions to lock down write access to executables, so it is invalid to assume you have write access on the jar.
The second point has you dead in the water for all OS impls (unless you can live with a fork, and the fork makes a lot of risky assumptions anyway)
Just write to a separate file and be done.
How about you write settings to a well known location outside of the JAR?
As alternatives for saving settings, consider one of these approaches:
java.util.prefs.Preferences, mentioned here.
JWS PersistenceService, described here.
Cookies, discussed in Accessing Cookies.
I am attempting to store the change made to my application's properties. The .properties file is located in resources package, which is different from the package that contains my UI and model.
I opened the package using:
this.getClass().getClassLoader().getResourceAsStream("resources/settings.properties")
Is there a functional equivalent of this that permits me to persist changes to the Properties Class in the same .Properties file?
In general, you cannot put stuff back into a resource you got from the classloader:
Class loader resources are often read-only; i.e. held in read-only files / read-only directories.
If you got the resource from a JAR file, JAR files are not simply updateable. (To "update" you need to extract the old JAR's contents and create a new JAR with the updated contents. It is all to do with the structure of ZIP files ...)
In some cases, the class loader resource will have been downloaded on-the-fly, and there is no way to push changes back to the place where you downloaded from.
Even if you can update a resource you got from the classloader, it is a bad idea / bad practice.
Doing this "pollutes" the clean application installation with a user's preferences. Among other things, this means that the installation cannot be shared with other users (unless you handle preferences for multiple users ...).
There are security issues with having applications installed as writeable so that embedded preferences can be updated. Think viruses! Think one user who might be inclined to trash another user's preferences!
There are administration issues with having user-specific copies of applications. And if the user has to install his own copy of an app, there are potential security issues with that as well.
There may be technical issues with file locking or caching on some platforms that either get in the way of (safe) updates or make it difficult for an application to load the updated resource without a restart.
Finally, this is NOT the way that system administrators (and educated users) expect software to behave. Java applications should deal with user preferences in the expected way:
You can use the Java Preferences API.
You can write a Properties file containing the preferences to an OS-appropriate user-writable directory.
On Windows, you could use a Windows-specific API to store the preferences in the Windows registry, except that this makes your application Windows dependent. (I can't see any real advantage in doing this, but I am not a Window expert.)
When you wrap your app up as a JAR file, your properties file will be one (possibly compressed) file within that JAR, and it would be a bad idea to try to write to your own JAR.
getResourceAsStream() is meant to open resources for reading, and these can be anywhere on the classpath. You can't write to URLs or inside JARs, you can only write to files, so it doesn't make sense to give you the same API for output.
Find yourself a directory you're allowed to write into, and write your properties there.
It may be a good idea to copy your properties from your installation classpath (possibly inside a JAR) directly out to a file if it doesn't yet exist, as a first operation upon application startup. This will give you a properties file you can write to, yet the master copy of this properties file will come from your project deliverable.
It sounds like you want to store user preferences. Consider using the Java Preferences API for that.
In addition to Carl's answer, if you're going to read and write to this file frequently, and expect that your application will expand in scope, consider whether to go one step (or several steps) further and use a file-based database like SQLite. There are a few JDBC wrappers for SQLite that would allow you to go beyond the basic string key-value lookup that the Java Properties interface provides.
even though writing the file into resources is not good practical, we still need to do it when our application only run in IDEA locally without deployment, then we can do it as below:
URL resource = Thread.currentThread().getContextClassLoader().getResource("settings.properties");
String path= resource.getPath();
OutputStream outputStream = new FileOutputStream(path);
//outputStream write