A multi-platform way to access jar located resources in java - 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.

Related

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.

Runtime.exec() fails with space in directory (Java)

I am trying to execute a process in the same directory as my Jar file by getting the location of the file with
private static File jarLocation = new File(Main.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getParentFile();
then calling
Runtime.getRuntime().exec("command", null, jarLocation);
This usually works just fine but when the path has a space in it I get "The directory name is invalid". I have attempted to add some debug code which prints the path of the directory which has replaced spaces with "%20" (I assume because the ASCII hex of space is 20). is there a way to be able to use a directory with spaces in its path?
That getPath() call, which is URL.getPath(), does not return a filesystem path. It returns the path portion of a URL. In the case of a file: URL, it will be a URL-encoded local filesystem path. If that original URL is in fact a file: URL, you need to use the URI and URL classes, or custom string processing, to convert that to a local filesystem path that the Runtime.exec() can work with.
This might work directly in your case.
File jarLocation = Paths.get(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI()).toFile();
You can also see the discussion at Converting Java file:// URL to File(...) path, platform independent, including UNC paths.

Instancing a java.io.File to read a resource from classpath

Supposing that I've a project structure as follows:
+ src
---+ main
------+ java
------+ resources
How can I define a java.io.File instance that is able to read an xml from resources folder?
It depends on what your program's working directory is.
You can get your working directory at runtime via System.getProperty("user.dir");
Here's a link with more info
Once you've got that, create a relative filepath pointing to your resource folder.
For example, if your working directory is src, create a relative filepath like so:
new File(Paths.get("main","resources").toString());
There are weaknesses with this approach as the actual filepath you use may change when you deploy your application, but it should get you through some simple development.
No, use an InputStream, with the path starting under resources.
InputStream in = getClass().getResourceAsStrem("/.../...");
Or an URL
URL url = getClass().getResource("/.../...");
This way, if the application is packed in a jar (case sensitive names!) it works too. The URL in that case is:
"jar:file://... .jar!/.../..."
If you need the resource as file, for instance to write to, you will need to copy the resource as initial template to some directory outside the application, like System.getProperty("user.home").
Path temp = Files.createTempFile("pref", "suffix.dat");
Files.copy(getClass().getResourceAsStream(...), temp, StandardCopyOption.REPLACE_EXISTING);
File file = temp.toFile();
As #mjaggard commented, createTempFile creates an empty file,
so Files.copy will normally fail unless with option REPLACE_EXISTING.

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

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!

Upload file to directory on server using Java and JSP - can't get path right

On my vps, I want to upload a file to the Logos directory.
The directory structure is as follows on my vps -
/home/webadmin/domain.com/html/Logos
When a file is uploaded through my jsp page, that file is renamed, and then I want to put it into the Logos directory.... but I can't seem to get the path right in my servlet code.
Snippet of servlet code -
String upload_directory="/Logos/"; // path to the upload folder
File savedFile = new File(upload_directory,BusinessName+"_Logo."+fileExtension);
//.....
//file saved to directory
//.....
I've tried many variations, but still fail. What is the proper way to specify the path?
Edited
The problem with using getServletContext() is that it returns the path to the directory where Tomcat and my webapp is...whereas I want to reach the directory where my html and image files are - under the root directory of the vps. How do I specify that path?
String server_path = getServletContext().getRealPath("/"); // get server path.
//server_path = /opt/tomcat6/webapps/domain.com/
String upload_directory = "Logos/"; // get path to the upload folder.
String complete_path = server_path + upload_directory; // get the complete path to the upload folder.
//complete_path = /opt/tomcat6/webapps/domain.com/Logos/
File savedFile = new File(complete_path,"NewLogo.jpg");
//savedFile = /opt/tomcat6/webapps/domain.com/Logos/NewLogo.jpg
It's a common practice to make the path for storage configurable - either via some application.properties file, or if you don't have such a properties file - as a context-param in web.xml. There you configure the path to be the absolute path, like:
configuredUploadDir=/home/webadmin/domain.com/html/Logos
Obtain that value in your code (depending on how you stored it), and have:
File uploadDir = new File(configuredUploadDir);
Note: make sure you have the permissions to read and write the target directory.
You can use following code in any jsp or servlet.
1) String serverPath= getServletContext().getRealPath("/");
This will give you full path of the server from root directory to your web application directory.
For me its: "D:\local\tomcat-6.0.29\webapps\myapp" when I sysout from myapp application.
Once you got the whole real path for the server system as above you can get the path relative to your directory. So if I have some data file in myapp\data - I can get it appending \data\filename to the serverPath which we got earlier.
This will work in all situation even you have multiple servers installed on the same system.
2) You can get server home from system properties using
System.getProperty("TOMCAT_HOME")
and then can use this absolute path in your program
3) To pass absolute directory path to any servlet using <init-param>
Hope this will work for you.
Well, the problem is: the File constructor doesn't create the file, only prepares to for the creation, then, after you construct a file instance you must invoke the method createNewFile(), and thats all.
The path "/Logos/" will attempt to create the file in the root of your system, which is not what you want. Look at the ServletContext.getRealPath() method.

Categories

Resources