A lot has been discussed already here about getting a resource.
If there is already a solution - please point me to it because I couldn't find.
I have a program which uses several jars.
To one of the jars I added a properties file under main/resources folder.
I've added the following method to the jar project in order to to read it:
public void loadAppPropertiesFile() {
try {
Properties prop = new Properties();
ClassLoader loader = Thread.currentThread().getContextClassLoader();
String resourcePath = this.getClass().getClassLoader().getResource("").getPath();
InputStream stream = loader.getResourceAsStream(resourcePath + "\\entities.properties");
prop.load(stream);
String default_ssl = prop.getProperty("default_ssl");
}catch (Exception e){
}
}
The problem (?) is that resourcePath gives me a path to the target\test-clasess but under the calling application directory although the loading code exists in the jar!
This the jar content:
The jar is added to the main project by maven dependency.
How can I overcome this state and read the jar resource file?
Thanks!
I would suggest using the classloader used to load the class, not the context classloader.
Then, you have two options to get at a resource at the root of the jar file:
Use Class.getResourceAsStream, passing in an absolute path (leading /)
Use ClassLoader.getResourceAsStream, passing in a relative path (just "entities.properties")
So either of:
InputStream stream = getClass().getResourceAsStream("/entities.properties");
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties");
Personally I'd use the first option as it's briefer and just as clear.
Can you try this:
InputStream stream = getClass().getClassLoader().getResourceAsStream("entities.properties")
Related
This question already has answers here:
Java Jar file: use resource errors: URI is not hierarchical
(6 answers)
Closed 6 years ago.
I have files in resource folder. For example if I need to get file from resource folder, I do like that:
File myFile= new File(MyClass.class.getResource(/myFile.jpg).toURI());
System.out.println(MyClass.class.getResource(/myFile.jpg).getPath());
I've tested and everything works!
The path is
/D:/java/projects/.../classes/X/Y/Z/myFile.jpg
But, If I create jar file, using , Maven:
mvn package
...and then start my app:
java -jar MyJar.jar
I have that following error:
Exception in thread "Thread-4" java.lang.RuntimeException: ხელმოწერის განხორციელება შეუძლებელია
Caused by: java.lang.IllegalArgumentException: URI is not hierarchical
at java.io.File.<init>(File.java:363)
...and path of file is:
file:/D:/java/projects/.../target/MyJar.jar!/X/Y/Z/myFile.jpg
This exception happens when I try to get file from resource folder. At this line. Why? Why have that problem in JAR file? What do you think?
Is there another way, to get the resource folder path?
You should be using
getResourceAsStream(...);
when the resource is bundled as a jar/war or any other single file package for that matter.
See the thing is, a jar is a single file (kind of like a zip file) holding lots of files together. From Os's pov, its a single file and if you want to access a part of the file(your image file) you must use it as a stream.
Documentation
Here is a solution for Eclipse RCP / Plugin developers:
Bundle bundle = Platform.getBundle("resource_from_some_plugin");
URL fileURL = bundle.getEntry("files/test.txt");
File file = null;
try {
URL resolvedFileURL = FileLocator.toFileURL(fileURL);
// We need to use the 3-arg constructor of URI in order to properly escape file system chars
URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null);
File file = new File(resolvedURI);
} catch (URISyntaxException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
It's very important to use FileLocator.toFileURL(fileURL) rather than resolve(fileURL)
, cause when the plugin is packed into a jar this will cause Eclipse to create an unpacked version in a temporary location so that the object can be accessed using File. For instance, I guess Lars Vogel has an error in his article - http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/
I face same issue when I was working on a project in my company. First Of All, The URI is not hierarichal Issue is because probably you are using "/" as file separator.
You must remember that "/" is for Windows and from OS to OS it changes, It may be different in Linux. Hence Use File.seperator .
So using
this.getClass().getClassLoader().getResource("res"+File.separator+"secondFolder")
may remove the URI not hierarichal. But Now you may face a Null Pointer Exception. I tried many different ways and then used JarEntries Class to solve it.
File jarFile = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
String actualFile = jarFile.getParentFile().getAbsolutePath()+File.separator+"Name_Of_Jar_File.jar";
System.out.println("jarFile is : "+jarFile.getAbsolutePath());
System.out.println("actulaFilePath is : "+actualFile);
final JarFile jar = new JarFile(actualFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
System.out.println("Reading entries in jar file ");
while(entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
final String name = jarEntry.getName();
if (name.startsWith("Might Specify a folder name you are searching for")) { //filter according to the path
System.out.println("file name is "+name);
System.out.println("is directory : "+jarEntry.isDirectory());
File scriptsFile = new File(name);
System.out.println("file names are : "+scriptsFile.getAbsolutePath());
}
}
jar.close();
You have to specify the jar name here explicitly. So Use this code, this will give you directory and sub directory inside the folder in jar.
I have this strange thing with input and output streams, whitch I just can't understand.
I use inputstream to read properties file from resources like this:
Properties prop = new Properties();
InputStream in = getClass().getResourceAsStream( "/resources/SQL.properties" );
rop.load(in);
return prop;
It finds my file and reds it succesfully. I try to write modificated settings like this:
prop.store(new FileOutputStream( "/resources/SQL.properties" ), null);
And I getting strange error from storing:
java.io.FileNotFoundException: \resources\SQL.properties (The system cannot find the path specified)
So why path to properties are changed? How to fix this?
I am using Netbeans on Windows
The problem is that getResourceAsStream() is resolving the path you give it relative to the classpath, while new FileOutputStream() creates the file directly in the filesystem. They have different starting points for the path.
In general you cannot write back to the source location from which a resource was loaded, as it may not exist in the filesystem at all. It may be in a jar file, for instance, and the JVM will not update the jar file.
May be it works
try
{
java.net.URL url = this.getClass().getResource("/resources/SQL.properties");
java.io.FileInputStream pin = new java.io.FileInputStream(url.getFile());
java.util.Properties props = new java.util.Properties();
props.load(pin);
}
catch(Exception ex)
{
ex.printStackTrace();
}
and check the below url
getResourceAsStream() vs FileInputStream
Please see this question: How can I save a file to the class path
And this answer https://stackoverflow.com/a/4714719/239168
In summary: you can't always trivially save back a file your read from the classpath (e.g. a file in a
jar)
However if it was indeed just a file on the classpath, the above answer has a nice approach
I have a class,in which ther is a func,which opens a properties file. When i write main in the same class & call that function,i am able to open the properties file n read. but, when i am tying to call the same func in my servlet by creating instance to that class, i get file not found exception.
This is the function, which i have written in my class to read properties file. And both my class and servlet are in src folder. I am using eclipse IDE.
Code:
private void readPropertiesFileAndFieldListData() {
String PROP_FILE = "./src/fields.properties";
try {
FileReader reader = new FileReader(PROP_FILE);
BufferedReader br = new BufferedReader(reader);
ArrayList<String> field = new ArrayList<String>();
while ((str = br.readLine()) != null) {
if (!str.startsWith("#") && str.trim().length() > 0) {
// System.out.println(str);
field.add(str);
count++;
}
}
}
You're relying on the current working directory of the disk file system path. The current working directory is dependent on how the application is started and is not controllable from inside your application. Relying on it is a very bad idea.
The normal practice is to put that file in the classpath or to add its path to the classpath. Your file is apparently already in the classpath (you placed it in the src folder), so you don't need to change anything else. You should should just get it from the classpath by the class loader. That's more portable than a disk file system path can ever be.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("fields.properties");
// ...
See also:
getResourceAsStream() vs FileInputStream
Unrelated to the concrete problem, you're basically reinventing the java.util.Properties class. Don't do that. Use the following construct:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("fields.properties");
Properties properties = new Properties();
properties.load(input);
// ...
PLease write a small test, for printing the file path of "PROP_FILE" to the log or console.
it seems, that you relativ path is incorrect.
Your relative path starting point can change, depending on where your *.exe file is started.
Your test should print
File tFile = new File(PROP_FILE);
// print tFile.getAbsolutePath()
Its better to get a special class by calling
SomeClass.class.getResource(name)
Eclipse RCP from the Bundle
Bundle.getResource(ResourcePathString)
EDIT:
Please check, whether the resource is part of your *.jar. It could be, that you missed to add it to the build.properties file.
Check whether the file is existing, before you read the properties file.
The directory structure of my application is as follows:-
My App
++++++ src
++++++++com
++++++++++readProp.java
++++++++resource
++++++++++message.properties
I am trying to read the file as follows:-
public Static final string FilePath="resource.message.properties"
Here the code to read the file. I tried using the following two techniques but to no use...
File accountPropertiesFile = new File(FacesContext.getCurrentInstance()
.getExternalContext().getRequestContextPath()
+ FilePath);
properties.load(externalContext.getResourceAsStream(FilePath));
But none yeild any sucess while reading through the Bean class. please help...
Your properties file is in the classpath. The java.io.File only understands the local disk file system structure. This is not going to work. You need to get it straight from the classpath by the classloader.
Here's a kickoff example:
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("/resources/messages.properties");
if (input != null) {
Properties properties = new Properties();
try {
properties.load(input);
} finally {
input.close();
}
}
I don't know if this is your problem, but you should try using slashes instead of periods, since they're stored as actual folders in the filesystem.
Is there a way for java program to determine its location in the file system?
You can use CodeSource#getLocation() for this. The CodeSource is available by ProtectionDomain#getCodeSource(). The ProtectionDomain in turn is available by Class#getProtectionDomain().
URL location = getClass().getProtectionDomain().getCodeSource().getLocation();
File file = new File(location.getPath());
// ...
This returns the exact location of the Class in question.
Update: as per the comments, it's apparently already in the classpath. You can then just use ClassLoader#getResource() wherein you pass the root-package-relative path.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL resource = classLoader.getResource("filename.ext");
File file = new File(resource.getPath());
// ...
You can even get it as an InputStream using ClassLoader#getResourceAsStream().
InputStream input = classLoader.getResourceAsStream("filename.ext");
// ...
That's also the normal way of using packaged resources. If it's located inside a package, then use for example com/example/filename.ext instead.
For me this worked, when I knew what was the exact name of the file:
File f = new File("OutFile.txt");
System.out.println("f.getAbsolutePath() = " + f.getAbsolutePath());
Or there is this solution too: http://docs.oracle.com/javase/tutorial/essential/io/find.html
if you want to get the "working directory" for the currently running program, then just use:
new File("");