URI scheme is not "file". Unable to read file from classpath - java

I have Java webapp and I am trying to read a file from classpth.
if (fileName == null){
fileName = Thread.currentThread().getContextClassLoader().getResource("config.properties");
}
objFile = new File(fileName.toURI());
I have config.properties in my classpath. WEB-INF/classes. When I inspect locally it gives: fileName.toURI(), it gives me file:/D:/dev/Tomcat_6_0/webapps/testApp/WEB-INF/classes/config.properties. And works fine.
Issue is on production linux server I am getting this path there vfsfile:/export/home/u/bin/jboss-5.1.0.BE/server/default/deploy/testApp.war/WEB-INF/classes/config.properties.
And I am getting following exception.
Caused by: java.lang.IllegalArgumentException: URI scheme is not "file"
at java.io.File.<init>(File.java:366)
at com.utils.ConfigLoader.loadConfigFilePath(ConfigLoader.java:87)
What is the workaround for handeling vfs?

You must not try to convert a resource from the classpath to a File. It may not even be a File if it's inside a WAR/JAR. The File class only represents filesystem objects.

Since you're loading resources (and they may be or may not be files, just imagine this properties file packed into jar/war), why don't you use openStream() on URL object? Then just read contents out of BufferedStream returned and that is it!

Related

ClassLoader.getResource returning null while using File.getAbsolutePath

I have a config.ini file I need to open that is quite far back in directory so I used File.getAbsolutePath() to set the base directory and concatenated the remainder of the path.
Printing the path, I get the correct path that I can paste into file explorer, but the object returned is null.
So I started by initializing my Properties and ClassLoader as such:
Properties prop = new Properties();
ClassLoader classLoader = Test.class.getClassLoader();
Then I create the path. I tried escaping a back slash(1) as well as forward slash(2), both return null but both paths work in file explorer.
String absPath = new File("").getAbsolutePath();
absPath = absPath.concat("\\resources\\config\\config.ini"); // (1)
absPath = absPath.concat("/resources/config/config.ini"); // (2)
then I try to set the URL to open an InputStream
URL res = Objects.requireNonNull(classLoader.getResource(absPath), "Unable to open config.ini");
InputStream is = new FileInputStream(res.getFile());
However, the following returns null.
classLoader.getResource(absPath)
I expected this to properly open the file because the path was correct. I am using Intelij and I read that I needed to add the .ini resource file under settings > compiler, which I did but that did not resolve my issue.
Thank you!
That's not the way to load resources via class-loaders.
If your classpath is something like the following ...
java -cp resources;lib/my.jar ... org.mypack.MyClass
then you load it with this path
getClassLoader().getResource("/config/config.ini");
Your classpath includes the resources folder, and the class-loader loads from there.
The absolute path of the OS is quite certainly not in classpath.
In any case, you must be certain that the resource folder is in classpath.
If your config file is not in classpath then you can't use classloaders to load that file.
Just one more thing, if your configuration is not in classpath, but in a child directory of your working dir, why can't you simply use new FileInputStream("resources/config/config.ini");

Spring does not find file in resources

i have following line
File file = ResourceUtils.getFile("classpath:calculation.csv");
and i also tried
File file = ResourceUtils.getFile("classpath:/calculation.csv");
but both will throw an error
java.io.FileNotFoundException: class path resource [calculation.csv] cannot be resolved to absolute file path because it does not exist
but i do have calculation.csv in by resources folder..
why is this?
I need to read file from resources folder, and it should also work in server enviroment
EDIT:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("calculation.csv").getFile());
works just as fine, so not at all..
EDIT2:
tried with folder.. i have both calculation.csv and csv/calculation.csv in my resources folder now..
none of the above work, with /csv/ added.
what kind of path does this thing want?!
EDIT3:
aaand
File file = new ClassPathResource("calculation.csv").getFile();
is also no go, what even is this..
Loading file (as FILE) wont work. You must use it as resource. Files inside JAR will not work as file anyway. This is also what your "check" code shows.
classLoader.getResource("calculation.csv") works, because you are using classloader to get resource, not filesystem to get file (which is what File api does). It could work, if you would deal with non packed application. Once you pack your app into JAR, file path will be like your/path/to/jar.jar!someResource - note ! mark (and that is what you would see as well). So basicly it will return File instance, you that you wont be able to use anyway, as file system has no access to it.
You could alternatively try to extract it first with ResourceUtiuls#extractJarFileURL(URL jarUrl) and then use extracted file.
I think, that in most cases Class#getResourceAsStream is the way to go and I think that it should fit your needs as well to read content of resource.

unable to get file using classLoader.getResource(fileName).getFile()

I made a maven web-app project in eclipse it was working fine on the machine on which I made this. but when importing this project to other machine in eclipse it gives me this exception while getting the file:
exception:D:\Eclipse%20Workspace.metadata.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\example\WEB-INF\classes\file.txt
(The system cannot find the path specified)
I am using this code to get a file:
public File getFile (String fileName) {
//Get file from resources folder
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource(fileName).getFile());
return file;
}
the file is in the resources folder of the project:
D:\Eclipse Workspace\Sentiment Analysis\example\src\main\resources
I go the path the exception message showing and found that the file is already been there.
The getFile method of URL does not convert a URL to a file. It just returns the portion of the URL after the host and port. URLs need to percent-escape a lot of characters, including spaces, so you cannot reliably use the URL's path portion as a file name. In fact, the exception is telling you exactly that: There is no directory named D:\Eclipse%20Workspace.metadata.plugins on your computer. (Go ahead and check.)
When you have a URL, you should not be trying to convert it to a File at all. You don't need to. You can read from a URL just as easily as from a file using the openStream method of URL.
But even that is not necessary, because you can also use the getResourceAsStream method to skip the URL entirely and get a readable InputStream:
InputStream stream = getClass().getResourceAsStream("/file.txt");
The code is looking for the file in the same directory as this code class resident. What is the package structure of this code?
Also, only Maven copy the resources into the class path. So if you compile and run using Eclipse then the resources folder won't be copied automatically.

How to get File from spring Resource

I have a Resource object (org.springframework.core.io.ClassPathResource). I need to get File object, but resource.getFile() throws an exeption File not Found. but after invoking resource.getURI() I have a result
jar:file:/D: .... file.jar!/com//test/0be14958-3778-40bf-bd3e-ee605fcdd3f0/verify
Directory is located in jar file. Is it possible to workaround limitation for ClassPathResource and create a File object?
I've tried a new File(resource.getURI()) but it fails with java.lang.IllegalArgumentException: URI is not hierarchical
what is my fault?
I don't think it's possible to get a java.io.File out of something that's in a JAR (because it's not actually a file). From the ClassPathResource JavaDoc:
Supports resolution as java.io.File if the class path resource resides in the file system, but not for resources in a JAR.
You don't mention why you need it as a java.io.File, but maybe you can refactor your code to use the ClassPathResource.getInputStream method (which enables you to read the resource)?
Either that or you could also use ClassPathResource.getInputStream to copy the file you want to a temporary file on the file system that you could then use as a straight up java.io.File.
File temp = File.createTempFile("temp", ".tmp");
org.apache.commons.io.IOUtils.copy(resource.getInputStream(), new FileOutputStream(temp));

A multi-platform way to access jar located resources in java

I need some code that could get an InputStream from a resource stored in some path into a jar file, this is the test code:
String res =File.separatorChar+ "folder"+File.separatorChar+"file.txt";
InputStream is = ReadRes.class.getResourceAsStream(res);
System.out.println(is);
Into my jar I have the directory folder/file.txt, in linux it works but on Windows I get a null value for is . What should I do?
Always use / when fetching the resource.
The resource is not a File, and the path is represented by an URL which always has forward slashes.

Categories

Resources