How to get the classloader's directory information? - java

Would like to build the absolutepath use this information. Anyone knows how?

If you know the name of the resource within the class path, i believe you can call
URL j = loader.getResource(name);
and from the URL you can tell where it is either in the file system, or in what jar it resides.

Judging by your other question, you are going about this wrong. If you only need to read from the resource, use getClass().getResource() to locate the resource and use it from the URL.
If OTOH the app. might also change the information in the resource, it is best to store a copy of the changed resource on the local file system. Don't store it in the 'user.dir' - which is fragile and unreliable, but a sub-directory (e.g. based on the reverse domain name) of 'user.home'.

Related

How to properly load .properties on distributable jar file? [duplicate]

I need to store data into files inside .jar file and read it again.
I know that I can use Class.getResourceAsStream() method but it returns an InputStream that I can read from. But I look for a way to write.
I need to store data into files inside .jar file and read it again
No you don't.
Instead store the 'default' file inside the Jar. If it is changed, store the altered file in another place. One common place is a sub-directory of user.home. When checking for the file, first check the existence of an altered file on the file system, and if it does not exist, load the default file.
Note that it is generally better to describe the goal, rather than the strategy. 'Store changed file in Jar' is a strategy, whereas 'Save preferences between runs' might be the goal.
Related: What is the XY problem?
This is not really supported. In principle, you could operate on the jar file, but there's no guarantee the new contents would be correctly loaded. Let your build tools manage the jar file -- and choose something else for persistent storage managed by your program itself. Like a file.
It is unlikely that you can change a loaded jar safely. Changing it while it is being used is not a good idea.
If you want to do this, use a plain file system directory and add/remove files from it. Even this may not work as you expect.
You can manipulate any jar file using the package java.util.jar (or indeed just java.util.zip). As files inside a jar will be compressed, this isn't the most time efficient way for you to store data.
You should probably use a directory somewhere else (e.g. System.getProperty("user.home") + "/.myProgram") or see java.util.prefs.
Class.getResource() returns a URL. Theoretically, you can use this URL to create your InputStream and OutputStream. But in most cases, the generated JAR is a read-only file (or archive). So your application might trip when trying to use it.

Reading a local folder from Jar file [duplicate]

I need to store data into files inside .jar file and read it again.
I know that I can use Class.getResourceAsStream() method but it returns an InputStream that I can read from. But I look for a way to write.
I need to store data into files inside .jar file and read it again
No you don't.
Instead store the 'default' file inside the Jar. If it is changed, store the altered file in another place. One common place is a sub-directory of user.home. When checking for the file, first check the existence of an altered file on the file system, and if it does not exist, load the default file.
Note that it is generally better to describe the goal, rather than the strategy. 'Store changed file in Jar' is a strategy, whereas 'Save preferences between runs' might be the goal.
Related: What is the XY problem?
This is not really supported. In principle, you could operate on the jar file, but there's no guarantee the new contents would be correctly loaded. Let your build tools manage the jar file -- and choose something else for persistent storage managed by your program itself. Like a file.
It is unlikely that you can change a loaded jar safely. Changing it while it is being used is not a good idea.
If you want to do this, use a plain file system directory and add/remove files from it. Even this may not work as you expect.
You can manipulate any jar file using the package java.util.jar (or indeed just java.util.zip). As files inside a jar will be compressed, this isn't the most time efficient way for you to store data.
You should probably use a directory somewhere else (e.g. System.getProperty("user.home") + "/.myProgram") or see java.util.prefs.
Class.getResource() returns a URL. Theoretically, you can use this URL to create your InputStream and OutputStream. But in most cases, the generated JAR is a read-only file (or archive). So your application might trip when trying to use it.

When distributing a Java-written application to multiple users, how do I reference a common directory that is unique to each user?

Disclaimer:I know that this is something that is covered very early in learning Java, however, I am just a hobbyist and I am self-taught. I am only as good as the information I find online is. Please do not be derisive or condescending. We were all new at one time.
As mentioned, I have a written a Java Form app. What it does it takes user input and writes it to an Excel file. How can I dynamically reference a file (the Excel, in particular) that is on each users' computer, found in a different directory but not have to hardcode each user's exact file path and distribute individually?
Thanks!
I think you are looking for user.home property.
System.getProperty("user.home");
Which will give you, say, c:\users\mk
and then you can append your path to that.
You could have the application ask the user for the path.
As part of the application configuration have the user define an environment variable using a known name with either the desired directory or the install directory (then use the variable to derive the desired directory).
for example:
tell the user to define BLAMMY_HOME which contains the install location of your software (named BLAMMY).
derive the desired directory by concatinating the value of BLAMMY_HOME and "/desired/directory/name".
or
have the user define BLAMMY_SPOT which contains the full path the the desired directory.
use the value of BLAMMY_SPOT in your application.
Defaulting to using user.home is fine, but I (personally) do not like that technique (as a user).
Take an example of 2 users
UserA path: /opt/file/directories/target (contains the excel file)
UserB path: /opt/directories/target (contains the excel file)
There's absolutely no way to find the target directory (except searching for it, but then you might find another one) unless the application has access to some out of band information. For example, Java offers the user.home property
String pathPrefix = System.getProperty("user.home");
so you can use that and make your target directory relative to that.
That's the whole purpose of applications having installation/working directories. As another example, take the Windows Registry. Imagine you had to download a patch from the internet. The patch itself wouldn't be able to check all the paths on the file system until it found yours (each user has a different one). Instead, it can find that path from the Windows Registry (or something comparable depending on the application).

Referencing a file in Eclipse without hard-coding the path?

I'm creating a dynamic web project in Eclipse where I frequently have write and read to and from an XML file. The file is in my project workspace in a folder called xml. I was wondering if Java provided some way to access the file without hard coding the file path. I've been looking around for a while for a solution but I haven't really founding anything that's really clear. Thanks!
You could just drop it in the classpath as suggested by others, but you won't be able to write to it.
Rather supply the absolute path as a VM argument or environment variable so that you don't need to hardcode it.
E.g.
-Dconfig.location=/path/to/config/file
with
File xmlFile = new File(System.getProperty("config.location"), "some.xml");
// ...
As a completely different alternative, you could consider a database.
You can get the proper path using the following from your Servlet:
String filename = getServletContext().getRealPath("/xml/config.xml");
NOTE:
getRealPath may return null if the file is inside a WAR file. In that case, if your file is in WEB_INF/classes, then you could use ServletContext.getResourceAsStream("/config.xml").
See this link:
I don't think the Servlet API gives you anything that would result in a reliable, writable, path to put work files in all containers. If your container runs the WebApp right out of the WAR, getRealPath() couldn't possibly point to something you can actually write to. I think that your only option here that is supported regardless of container is to hard code some path in the web.xml. Do it as a Context Parameter and you may be able to change it at deployment time. At the end of the day, you must declare a fully qualified path in either code or configuration to get the effect you seek.
Alternatively, do you really need to know the name of the file? In some Servlet apps I've managed to get the effect of dynamically writable storage through plain-jane java.io.file.createTempFile: http://docs.oracle.com/javase/1.4.2/docs/api/java/io/File.html#createTempFile(java.lang.String, java.lang.String)

Servlet : What exactly the use of context.getRealPath(" ");

As i know it returns the application path? But what exactly the use of it.
In many environments the application user is not allowed to read any files outside of the deployment directory. This is mostly done for security purposes - for example if someone hacks your application they won't be able to read a passwords file.
And in professionally managed environments developers often don't have a say in which directory the application will be placed.
So if you need to read a file like properties, images, certificates, etc. you can place it in the application directory (or .war file) and use getRealPath("") to get the path you need to load.
As an alternative you can place the external files on the classpath but there are sometimes issues with this. For large files most app servers will try to load the entire file into memory and cache it if it is on the classpath.
The getRealPath() gives the absolute path (on the file system) leading to a file specified in the parameters of the call. It returns the path in the format specific to the OS.
The getContextPath() on the other hand returns the URI or the relative path to the resource.
As far as I remember, I've used it to save images or other data files, since it allows you to see where your application is deployed at the moment. For example, Eclipse and Tomcat will create a temporary folder that's buried deep somewhere within your Eclipse profile and deploy the app there.
This is a real path in file system.
From javadoc:
The real path returned will be in a form appropriate to the computer and operating system on which the servlet container is running, including the proper path separators. This method returns null if the servlet container cannot translate the virtual path to a real path for any reason (such as when the content is being made available from a .war archive).
I think it is very clear. Why do we need this? Sometimes web applications perform some manipulation in file system. For example read stuff from files, write files etc. This API allows you to access the place where your JSPs and other stuff is really stored.

Categories