I need the URI of a file (which I put in the resources directory). If I use
MyClass.class.getClassLoader().getResource(resource)
I get
java.lang.IllegalArgumentException: URI is not hierarchical
Otherwise, if I use ClassLoader.getSystemResource(resource) it returns null.
Are you loading the file from inside a jar? If so, the OS is unable to form a java File instance from inside a jar. To be able to load it, try open it as a Stream. "filepath" should start with a "/".
MyClass.class.getClass().getResourceAsStream( filepath );
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.
Related
I'm trying to read a text file located in src/main/resources/test/file.txt. I'm trying to get the path of the file using String path = getClass().getResource("/text/file.txt").getFile(); but when I try to read it I get a FileNotFoundException. I tried putting many different paths, all of which failed. How can I go about doing this?
The idea of putting something into the src/main/resources tree is that it will be copied into the JAR file that you build from your project. It will then be available to your application via the Class methods getResource(String) and getResourceAsStream(String) methods.
When you are running in your application in the development environment, it is certainly possible to use FileInputStream etcetera to access the resource. But this won't work in production. In production, the resources will then be inside your app's JAR file. FileInputStream cannot open a JAR file and its contents by name.
When you do this:
getClass().getResource("/text/file.txt");
you get a URL for the resource, which will look something like this:
jar:file:/path/to/your.jar!/text/file.txt"
It is not possible to turn that into a pathname the FileInputStream will understand. Whatever you try will give you a FileNotFoundException ... or something that is not the resource you want to read.
So what to do?
You have a few options, depending on your application's requirements.
You can use getResourceAsStream and use the resulting input stream directly.
You can copy the contents of getResourceAsStream to a temporary file, and then use the pathname of the temporary file.
You can create an application specific directory (e.g. in the user's home directory) and extract the file you need from the JAR into the directory. You might do this the first time the application runs.
You could open the JAR file as a JarFile and use that API to open an InputStream for the resource. But this assumes that that the resources are in a JAR ... and on some platforms (e.g. Windows) you may encounter problems with file locking. (And it would be a bad idea to attempt to update the resource in the JAR.)
Try giving complete path of the file from the disk.
C:\Users\MyUser\Desktop\file name with extension
I am loading my properties file using the class loader as follows.
Properties prop = new Properties();
prop.load(MyClass.class.getResourseAsStream("/Property.properties"));
Now, using this method I am able to read the properties file. I want to write some data to the property file. I don't know the path of the property file. How do I store the data to the property file then ?
Update
I tried the following, but it doesn't give me the correct path:
File propFile = new File("Property.properties");
System.out.println(propFile.getAbsolutePath());
I don't think you can in a generic way that would always work, because your properties file could be bundled inside a jar, etc. You can get the URL via getResource(String) and then do something with that URL, for example if it's a file URL, you could get the file name there.
URL u=MyClass.class.getResource("/Property.properties");
if ("file".equals(u.getProtocol()){
File f=new File(u.toURI());
}
But that wouldn't work in all cases.
I would write the modified value to a file in a well known location, and use the bundled Properties as the default value, that are overriden by the values in the file.
There are two parts to your question.
First, the reading part. You said: "I am loading my properties file ..." using the code you provided. This code treats the file as a "resource" and loads it using the class loader. The class loader mechanism in the Java Runtime comes into picture here. Roughly speaking, this mechanism searches for it in your application's current classpath and makes the input stream associated with first matching resource available to your code. It may be fine in your case, however, you should realize that if there are multiple properties files by the same name in different parts of your classpath (e.g. different JAR files having the same config file), then you may not know which file is being read. The only way to ensure that you are reading the right file from the classpath is to ensure that you have that config file in a unique place in your application's classpath.
This seems to work for you. Reading from a file is easier, than, say writing to a file.
In the second part, you want to write to a file. It's important to note that you should know the exact whereabouts of the file you are writing to. If you rather unknowingly convert it to an output stream, then you might end up trying to write to a stream that you are not allowed to write to. So, here, you should try to find the location (path) of the actual, physical file, for example, on a computer's hard drive. That path is something you should know before you write and run this program. Remember that a file always exists in a folder or a directory.
Your attempt:
File propFile = new File("Property.properties");
System.out.println(propFile.getAbsolutePath());
to find the location or path of the file you want to write to fails because when you do new File("Property.properties");, Java tries to refer to a file (does not do anything yet with the operating system) that resides in the Java Runtime's current working directory. This refers to the location given by System.getProperty("user.dir"). So, your propFile refers to a (hypothetical) file in that folder and the call to getAbsolutePath() prints its path. This is not the file that you want because you are trying to write to a file whose path you don't know. So, you should find the path of the file and then use a BufferedWriter backed by a FileWriter or BufferedOutputStream backed by a FileOutputStream to write to this file. Make sure that the file you want to write to exists and you have permission to write to it.
Essentially get the resource as an OutputStream, then pass it to the store() method of your Properties object.
Details here:
http://www.drdobbs.com/jvm/readwrite-properties-files-in-java/231000005
I have a web application running under tomcat 7, and in one of the class, Im trying to read a file in one of the jar under WEB-INF/lib folder.
URL resourceURL = MyClass.class.getClassLoader().getResource("xml/xslt/master.xsl");
File xslfile = new File(resourceURL.getPath());
AssertUtil.assertTrue(xslfile.exists(),"xsl file not found");
Both MyClass and master.xsl resides in the same jar and there is no issue with packaging. But above snippet fails in the assertion statement as xslfile.exists returns false. The URL correctly resolves to the location of the file inside the jar as given below
file:/<MY_WEBAPP_LOCATION>/MyApp/WEB-INF/lib/MyComponent.jar!/xml/xslt/master.xsl
where MY_WEBAPP_LOCATION corresponds to the absolute path to my tomcat servers webapp directory.
But if I rewrite the code as below to read as inputstream, it works fine.
InputStream xslFile = MyClass.class.getClassLoader().getResourceAsStream("xml/xslt/master.xsl");
Can anyone explain what is preventing the creation of File from the jar resource, whereas the inputstream creation is working perfectly fine. Is there any additional permission settings needed from tomcat side, to read a file inside jar ?
EDIT: One more observation, if the file is placed under WEB-INF/classes, creation of File with above code works fine. Issue is only when it is placed in a jar under WEB-INF/lib
Be careful it seems that ClassLoader.getResource does not handle relative path.
See this.
GetResourceAsStream happens to take the path relative to the ClassLoader (and not the class !!). I think you're lucky enough that there are the same here.
If it is a Desktop application getResource() will work
But as this is a web application the resource needs to be extracted from Context , hence getResoruceAsStream()
It is not a permission problem, but the use of java.io.File API - in particular constructor http://docs.oracle.com/javase/7/docs/api/java/io/File.html#File%28java.lang.String%29
When you are constructing File object using
File xslfile = new File(resourceURL.getPath());
you are using java.io.File#File(String) method which expects an "abstract pathname". What is an acceptable/valid pathname is described by javadoc of the File class: http://docs.oracle.com/javase/7/docs/api/java/io/File.html
String value that your are getting from getPath() method:
file:/<MY_WEBAPP_LOCATION>/MyApp/WEB-INF/lib/MyComponent.jar!/xml/xslt/master.xsl
simply does not constitute a valid "abstract pathname" - it is a URL that is converted to a java.lang.String (and IMHO should be returned with URL scheme of "jar" and not "file"). Therefore a call to
isExist()
returns false as there is no file with such name on your disk.
On the other hand if the resource is outside of a jar (e.g. under WEB-INF/classes directory) resourceURL.getPath() will return a value that presents a valid abstract pathname as the resource in question is indeed a simple file.
When you use java.lang.ClassLoader#getResourceAsStream(java.lang.String) the method streams out the resource directly into a java.lang.InputStream and might not even use File class in its implementation.
Im trying to get the file path of a document that is packaged as a resource in a jar file so that i can display it in a swing application. The way I have it now works when I run it from eclipse but if I export it to a runnable jar file I can't access the the documents that are packaged in the jar file. How can I get the file path of the document when its inside the jar file?
Here is the line of code showing how I am trying to access the document:
File document = new File(getClass().getResource("/resources/documents/document.pdf").getPath());
The only kind of "file path" that exists for something inside a JAR file is the path relative to the root of the JAR. But in your case it seems that you know it already (it's "/resources/documents/document.pdf"). Files inside a JAR file have no path that you can use to access them directly as they don't exist within the real file system. You need to use either getResource() or getResourceAsStream() to access them. I don't remember right now which classes are used for images in Swing, but look closely at those classes - they should have overloaded methods that accept something like InputStream or URL instead of file path.
I'm working with text files on Java. On Ubuntu 10.
But, I'm having problems with path dir.
Example:
saveFile("textFile.txt","abc");
This abstract function basically put "abc" on "textFile.txt".
I compile this file, and create a jar file (using NetBeans).
When I run the app, and call saveFile("textFile.txt","abc"), textFile.txt is saved on \home. I don't want this. I want that textFile.txtgo to pathDir inside jar file.
How do I write in this file, this same way?
When reading resources from a JAR file, you cannot use the File API. Instead, you use Class.getResourceAsStream(), like this:
reader = new InputStreamReader(MyClass.class.getResourceAsStream(
"/apathdir/textFile.txt"), "UTF-8");
Note also how the encoding is specified. FileReader does not allow that, which is why it should usually be avoided.
Iwant to know, if fileName =
"textFile.txt", what is the path dir
of this file?
If you only use a bare file name (without giving a directory), the JVM will look for the file in the current directory of the JVM process; that is usually the directory you ran the JVM (the java executable) from.
how do i do to set
/apathdir/textFile.txt?. apathdir is a
directory that is inside jar file.
I tried: fileName = "/apathdir/textFile.txt", but doesn't works.
If you want to load a file from inside a JAR file, you cannot load it using FileReader. You need to use ClassLoader.getSystemResourceAsStream() (or Class.getResourceAsStream). See e.g. this article for an explanation:
http://www.devx.com/tips/Tip/5697