I'm loading a properties using below code:
ResourceBoundle boundle = ResourceBundle.getBundle("file")
I want to know the absolute path of the loaded file. For example if I execute this code in a web application in webapps folder of a tomcat I want to obtain:
c:\tomcat8\webapps\example\WEB-INF\classes\file.properties.
How can I know this path?
I have 'resolved' my problem with this post 'Getting current working directory'. For my problem I only need this, once I know the working directory I can find the absolute path
public class Test {
public static void main(String... args) throws Exception {
URL location = Test.class.getProtectionDomain().getCodeSource().getLocation();
System.out.println(location.getFile());
}}
I think that perhaps this solution does not cover all the situations, but it is enough for me.
You can't get the physical location from a ResourceBundle, but if you know the path that was used to load it, then you can find out the physical location of that. Like this:
String resourceToLoad = "file";
URL url = this.getClassLoader().getResource(resourceToLoad);
ResourceBoundle bundle = ResourceBundle.getBundle(resourceToLoad);
The url will have the physical location of the resource -- at least most of the time.
Remember that a ResourceBundle can also be backed by a Java class rather than something like a properties file. ClassLoader.getResource doesn't understand the mapping between ResourceBundle and Java classes. If you want to be able to support those, you'll have to implement a similar algorithm to what ResourceBundle does in order to search for classes that match it's scheme.
Related
I am trying to load an image to use as an icon in my application. The appropriate method according to this tutorial is:
protected ImageIcon createImageIcon(String path, String description)
{
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
So, I placed the location of the file, and passed it as a parameter to this function. This didn't work, i.e. imgURL was null. When I tried creating the ImageIcon by passing in the path explicitly:
ImageIcon icon = new ImageIcon(path,"My Icon Image");
It worked great! So the application can pick up the image from an explicitly defined path, but didn't pick up the image using getResources(). In both cases, the value of the path variable is the same. Why wouldn't it work? How are resources found by the class loader?
Thanks.
getClass().getResource(path) loads resources from the classpath, not from a filesystem path.
You can request a path in this format:
/package/path/to/the/resource.ext
Even the bytes for creating the classes in memory are found this way:
my.Class -> /my/Class.class
and getResource will give you a URL which can be used to retrieve an InputStream.
But... I'd recommend using directly getClass().getResourceAsStream(...) with the same argument, because it returns directly the InputStream and don't have to worry about creating a (probably complex) URL object that has to know how to create the InputStream.
In short: try using getResourceAsStream and some constructor of ImageIcon that uses an InputStream as an argument.
Classloaders
Be careful if your app has many classloaders. If you have a simple standalone application (no servers or complex things) you shouldn't worry. I don't think it's the case provided ImageIcon was capable of finding it.
Edit: classpath
getResource is—as mattb says—for loading resources from the classpath (from your .jar or classpath directory). If you are bundling an app it's nice to have altogether, so you could include the icon file inside the jar of your app and obtain it this way.
As a noobie I was confused by this until I realized that the so called "path" is the path relative to the MyClass.class file in the file system and not the MyClass.java file. My IDE copies the resources (like xx.jpg, xx.xml) to a directory local to the MyClass.class. For example, inside a pkg directory called "target/classes/pkg. The class-file location may be different for different IDE's and depending on how the build is structured for your application. You should first explore the file system and find the location of the MyClass.class file and the copied location of the associated resource you are seeking to extract. Then determine the path relative to the MyClass.class file and write that as a string value with "dots" and "slashes".
For example, here is how I make an app1.fxml file available to my javafx application where the relevant "MyClass.class" is implicitly "Main.class". The Main.java file is where this line of resource-calling code is contained. In my specific case the resources are copied to a location at the same level as the enclosing package folder. That is: /target/classes/pkg/Main.class and /target/classes/app1.fxml. So paraphrasing...the relative reference "../app1.fxml" is "start from Main.class, go up one directory level, now you can see the resource".
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("../app1.fxml"));
Note that in this relative-path string "../app1.fxml", the first two dots reference the directory enclosing Main.class and the single "." indicates a file extension to follow. After these details become second nature, you will forget why it was confusing.
getResource by example:
package szb.testGetResource;
public class TestGetResource {
private void testIt() {
System.out.println("test1: "+TestGetResource.class.getResource("test.css"));
System.out.println("test2: "+getClass().getResource("test.css"));
}
public static void main(String[] args) {
new TestGetResource().testIt();
}
}
output:
test1: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
test2: file:/home/szb/projects/test/bin/szb/testGetResource/test.css
getResourceAsStream() look inside of your resource folder. So the fil shold be placed inside of the defined resource-folder
i.e if the file reside in /src/main/resources/properties --> then the path should be /properties/yourFilename.
getClass.getResourceAsStream(/properties/yourFilename)
This is what I've tried:
String myPath = myStaticClass.class.getResource("en-us").getPath();
// returns C:/Users/Charles/Workspace/ProjectName/target/classes/
My resources are in C:/Users/Charles/Workspace/ProjectName/src/main/resources
Does anyone know why this is happening?
Edit:
I suppose I should have mentioned that the path is being used in a library to load resources, but is failing.
That is where your compiled code is put when you use maven to build your project. Your resources are being copied to the target/classes folder as part of the build process.
If you then deploy your application to another location, you will find that your code will return the new path to the resource.
Edit
As per your comment, try using the following to load your resource:
InputStream resourceStream = myStaticClass.class.getClassLoader().getResourceAsStream("en-us");
This uses the current class's class loader to locate and provide an InputStream to your resource.
When you run mvn compile, one of the steps along the way is to copy your resources directory to the target/classes directory. Now usually if you call myStaticClass.class.getResource, the path you pass in will have target/classes as the root. So lets say you have a file at src/main/resources/my.file.txt You will be able to get it by calling myStaticClass.class.getResource("/my.file.txt");
The thing you're probably forgetting is the "/" there. Without that "/", it will look relative to your class' directory.
Alternatively, you could do this: ClassLoader.getSystemClassLoader().getResource("my.file.txt").getPath(). Notice the lack of a slash.
You are asking why this is happening and you are saying you want to load the resources.
The "why": see the other posts. No reason to duplicate them here.
The "how": the following code shows how to load the resources. Assuming they are in a file called "your.resources" and that this file is in the classpath; which, according to your post, it is.
import java.io.IOException;
import java.util.Properties;
public class Test {
public Test() throws IOException
{
final Properties properties = new Properties();
properties.load(this.getClass().getResourceAsStream("your.resources"));
System.out.println(properties);
}
public static void main(String[] args) throws IOException {
new Test();
}
}
Note that you don't need to provide the full path of the resources. As long as they are in the classpath, this will find them.
I have a java app where I'm trying to load a text file that will be included in the jar.
When I do getClass().getResource("/a/b/c/"), it's able to create the URL for that path and I can print it out and everything looks fine.
However, if I try getClass().getResource(/a/b/../"), then I get a null URL back.
It seems to not like the .. in the path. Anyone see what I'm doing wrong? I can post more code if it would be helpful.
The normalize() methods (there are four of them) in the FilenameUtils class could help you. It's in the Apache Commons IO library.
final String name = "/a/b/../";
final String normalizedName = FilenameUtils.normalize(name, true); // "/a/"
getClass().getResource(normalizedName);
The path you specify in getResource() is not a file system path and can not be resolved canonically in the same way as paths are resolved by File object (and its ilk). Can I take it that you are trying to read a resource relative to another path?
I have an I18n helper class that can find out the available Locales by looking at the name of the files inside the application's Jar.
private static void addLocalesFromJar(List<Locale> locales) throws IOException {
ProtectionDomain domain = I18n.class.getProtectionDomain();
CodeSource src = domain.getCodeSource();
URL url = src.getLocation();
JarInputStream jar = new JarInputStream(url.openStream());
while (true) {
JarEntry entry = jar.getNextJarEntry();
if (entry == null) {
break;
}
String name = entry.getName();
// ...
}
}
Currently, this isn't working - jar.getNextJarEntry() seems to always return null. I have no idea why that's happening, all I know is that url is set to rsrc:./. I have never seen that protocol, and couldn't find anything about it.
Curiously, this works:
class Main {
public static void main(String[] args) {
URL url = Main.class.getProtectionDomain().getCodeSource().getLocation();
JarInputStream jar = new JarInputStream(url.openStream());
while (true) {
JarEntry entry = jar.getNextJarEntry();
if (entry == null) {
break;
}
System.out.println(entry.getName());
}
}
}
In this version, even though there is practically no difference between them, the url is correctly set to the path of the Jar file.
Why doesn't the first version work, and what is breaking it?
UPDATE:
The working example really only works if I don't use Eclipse to export it. It worked just fine in NetBeans, but in the Eclipse version the URL got set to rsrc:./ too.
Since I exported it with Package required libraries into generated JAR library handling, Eclipse put its jarinjarloader in my Jar so I can have all dependencies inside it. It works fine with the other settings, but is there any way to make this work independently of them?
Another question
At the moment, that class is part of my application, but I plan to put it in a separate library. In that case, how can I make sure it will work with separate Jars?
The problem is the jarinjarloader ClassLoader that is being used by Eclipse. Apparently it is using its own custom rsrc: URL scheme to point to jar files stored inside the main jar file. This scheme is not understood by your URL stream handler factory, so the openStream() method returns null which causes the problem that you're seeing.
This answers the second part of your question about separate jars - not only will this work, it's the only way that it will work. You need to change your main application to use separate jars instead of bundling them all up inside the main jar. If you're building a web application, copy them into the WEB-INF/lib directory and you're fine. If you're building a desktop application, add a relative path reference in the META-INF/MANIFEST.MF to the other jars, and they will automatically be included as part of the classpath when you run the main jar.
The code may or may not result into the jar file where I18n resides. Also getProtectionDomain can be null. It depends how the classloader is implemented.
ProtectionDomain domain = I18n.class.getProtectionDomain();
CodeSource src = domain.getCodeSource();
URL url = src.getLocation();
about the rsrc:./ protocol, the classloader is free to use whatever URL they please (or name it for that matter)
try this out, you might get lucky :)
URL url = getClass().getResource(getClass().getSimpleName()+".class");
java.net.JarURLConnection conn = (java.net.JarURLConnection) url.openConnection();
Enumeration<JarEntry> e = conn.getJarFile().entries();
...
and good luck!
Eclipse's jarinjarloader loads everything using the system classloader and it never knows what jar file it was loaded from. That's why you can't get the jar URL for a rsrc: url.
I suggest storing the list of locales in a file in each application jar, e.g. META-INF/locales. Then you can use ClassLoader.getResources("META-INF/locales") to get the list of all the files with that name in the classpath and combine them to obtain the full list of locales.
I use System.getProperty("java.class.path") for getting the location of the jar. I do not know if that makes a difference. I have not explored the ProtectDomain path so I cannot help you there, sorry. As for multiple jars, just iterate through those jar file also.
How can I get the relative path of the folders in my project using code?
I've created a new folder in my project and I want its relative path so no matter where the app is, the path will be correct.
I'm trying to do it in my class which extends android.app.Activity.
Perhaps something similar to "get file path from asset".
Make use of the classpath.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource("path/to/folder");
File file = new File(url.toURI());
// ...
Are you looking for the root folder of the application? Then I would use
String path = getClass().getClassLoader().getResource(".").getPath();
to actually "find out where I am".
File relativeFile = new File(getClass().getResource("/icons/forIcon.png").toURI());
myJFrame.setIconImage(tk.getImage(relativeFile.getAbsolutePath()));
With this I found my project path:
new File("").getAbsolutePath();
this return "c:\Projects\SampleProject"
You can check this sample code to understand how you can access the relative path using the java sample code
import java.io.File;
public class MainClass {
public static void main(String[] args) {
File relative = new File("html/javafaq/index.html");
System.out.println("relative: ");
System.out.println(relative.getName());
System.out.println(relative.getPath());
}
}
Here getPath will display the relative path of the file.
In Android, application-level meta data is accessed through the Context reference, which an activity is a descendant of.
For example, you can get the source directory via the getApplicationInfo().sourceDir property.
There are methods for other folders as well (assets directory, data dir, database dir, etc.).
Generally we want to add images, txt, doc and etc files inside our Java project and specific folder such as /images.
I found in search that in JAVA, we can get path from Root to folder which we specify as,
String myStorageFolder= "/images"; // this is folder name in where I want to store files.
String getImageFolderPath= request.getServletContext().getRealPath(myStorageFolder);
Here, request is object of HttpServletRequest. It will get the whole path from Root to /images folder. You will get output like,
C:\Users\STARK\Workspaces\MyEclipse.metadata.me_tcat7\webapps\JavaProject\images
With System.getProperty("user.dir") you get the "Base of non-absolute paths" look at
Java Library Description