I try to write and read to the file in my java project file called Books.txt. The problem is that I can access the file only if partialPath has full path to the file.
He
I also feel that files created (and later possibly modified and or deleted) by your running Java application is usually better to be placed in a location of the file system that is away from your java application installed home directory. An example might be the 'C:\ProgramData\ApplicationNameFiles\' for the Windows operating system or something similar for other OS platforms. In my opinion, at least for me, I feel it provides less chance of corruption to essential application files due to a poorly maintained drive or, accidental deletion by a User that opens up a File Explorer and decides to take it upon him/her self to clean their system of so called unnecessary files, and other not so obvious reasons.
Because Java can run on almost any platform and such data file locations are platform specific the User should be allowed to select the location to where these files can be created and manipulated from. This location then can be saved as a Property. Indeed, slightly more work but IMHO I feel it may be well worth it.
It is obviously much easier to create a directory (folder) within the install home directory of your JAR file when it's first started and then store and manipulate your application's created data files from there. Definitely much easier to find but then again...that would be a matter of opinion and it wouldn't be mine. Never-the-less if you're bent on doing it this way then your Java application's Install Utility should definitely know where that install path would be, it is therefore just a matter of storing that location somewhere.
No Install Utility? Well then your Java application will definitely need a means to know from where your JAR file is running from and the following code is one way to do that:
public String applicationPath(Class mainStartupClassName) {
try {
String path = mainStartupClassName.getProtectionDomain().getCodeSource().getLocation().getPath();
String pathDecoded = URLDecoder.decode(path, "UTF-8");
pathDecoded = pathDecoded.trim().replace("/", File.separator);
if (pathDecoded.startsWith(File.separator)) {
pathDecoded = pathDecoded.substring(1);
}
return pathDecoded;
}
catch (UnsupportedEncodingException ex) {
Logger.getLogger("applicationPath() Method").log(Level.SEVERE, null, ex);
}
return null;
}
And here is how you would use this method:
String appPath = applicationPath(MyMainStartupClassName.class);
Do keep in mind that if this method is run from within your IDE it will most likely not return the path to your JAR file but instead point to a folder where your classes are stored for the application build.
Here is a code snippet of the Drombler Commons - Client Startup code I wrote, to determine the location of the executable jar. Replace DromblerClientStarter
with your main class.
This should work at least when you're running your application as an executable JAR file.
/**
* The jar URI prefix "jar:"
*/
private static final String FULL_JAR_URI_PREFIX = "jar:";
/**
* Length of the jar URI prefix "jar:"
*/
private static final int FULL_JAR_URI_PREFIX_LENGTH = 4;
private Path determineMainJarPath() throws URISyntaxException {
Class<DromblerClientStarter> type = DromblerClientStarter.class;
String jarResourceURIString = type.getResource("/" + type.getName().replace(".", "/") + ".class").toURI().
toString();
int endOfJarPathIndex = jarResourceURIString.indexOf("!/");
String mainJarURIString = endOfJarPathIndex >= 0 ? jarResourceURIString.substring(0, endOfJarPathIndex)
: jarResourceURIString;
if (mainJarURIString.startsWith(FULL_JAR_URI_PREFIX)) {
mainJarURIString = mainJarURIString.substring(FULL_JAR_URI_PREFIX_LENGTH);
}
Path mainJarPath = Paths.get(URI.create(mainJarURIString));
return mainJarPath;
}
Depending on where you bundle Books.txt in your application distribution package, you can use this mainJarPath to determine the path of Books.txt.
This is not a unique issue to Java, it's a problem faced by any developer of any language wishing to write data locally to the disk. The are many parts to this problem.
If you want to be able to write to the file (and presumably, read the changes), then you need to devise a solution which allows you find the file in a platform independent way.
While most OS's do have some conventions governing this, this doesn't mean they are always used, for what ever reason.
Also, on some OS's, you are actively restricted from writing to the "installation" location. Windows 8+ doesn't allow you to write to the "Program Files" directory, and in Java, this usually (or at least when I was dealing with it) fails silently.
On MacOS, if you're using a "app bundle", the working directory is automatically set to the user's home directory, making it even more difficult to manage
A program can be installed in one location, but executed from a different location, this will change the working directory location. Many command line tools suffer from this issue and use different conventions to work around it (ever wonder what the JAVA_HOME
environment variable is for