Java NIO filesystem - java

I am trying to create a Java Swing Application in which I will be storing some image files and CSV files in a subdiretory
com/p/d/resources/project/MyProject
In above project there will be other sub-directories in which I will be storing the images and CSV files. How to access above directory in seamless way. That is even if I run this project as a JAR(which I will ultimately do) or on Eclipse it should give me the access to above directory either as java.nio.file.Path OR java.io.File.
I know I can create a filsystem to iterate JAR but the same code doesn't work when I run it as application in Eclipse. Following is the code I am using for JAR file scenario:
String projectLocationPath = ApplicationProperties
.get(PhaserDesktopConstants.PROJECT_LOCATION_PATH);
CodeSource src = MainController.class.getProtectionDomain()
.getCodeSource();
if (src != null) {
URL jar = src.getLocation();
FileSystem fs = FileSystems.newFileSystem(jar.toURI().normalize(), null);
Path projectDirectory = fs.getPath(projectLocationPath);
if (!Files.isDirectory(projectDirectory)) {
return null;
}
}
Where PhaserDesktopConstants.PROJECT_LOCATION_PATH represents path I gave above. I want to run above code in both scenarios with JAR and without JAR.
I get following path
file:/D:/shailesh/technical/work/eclipse_ws/Phaser%20Desktop/bin/
when I run it in Eclipse and calling
FileSystems.newFileSystem(..)
with this gives me exception
java.lang.IllegalArgumentException: Path component should be '/'
Following some posts on SO I tried hardcoding and changing the path from
file:/D:/shailesh/technical/work/eclipse_ws/Phaser%20Desktop/bin/
to
file:///D:/shailesh/technical/work/eclipse_ws/Phaser%20Desktop/bin/
file://D:/shailesh/technical/work/eclipse_ws/Phaser%20Desktop/bin/
file:///shailesh/technical/work/eclipse_ws/Phaser%20Desktop/bin/
file://shailesh/technical/work/eclipse_ws/Phaser%20Desktop/bin/
but none worked.
Just an Update:
when I debug in eclipse my JAR it gives me following path as location of CodeSource:
file:/D:/shailesh/technical/PhaserD.jar
however error is same its not able to create the filesystem. My OS is Windows 7. JDK 7

You can replace the . with ./../ to switch to a parent directory or with any reference path you'd like. p holds the absolute path, and you can remove the toAbsolutePath() to obtain the referencePath.
Path p = FileSystems.getDefault().getPath(".").toAbsolutePath();
System.out.println(p);

Related

Java classloader not able to find resource in jar file

I have a runnable jar file which is not able to access my resources which reside outside of the default src directory. Based on my understanding from What is the difference between Class.getResource() and ClassLoader.getResource(), I should be able to access root/res/img/img1.png (see folder setup below) by using the following getResourceFile function:
public class Foo {
private static final ClassLoader CLASS_LOADER = Foo.class.getClassLoader();
public static File getResourceFile(String relativePath) {
// Since I'm using getClassLoader, the path will resolve starting from
// the root of the classpath and it'll take an absolute resource name
// usage: getResourceFile("img/img1.png")
// result: Exception in thread "main" java.lang.NullPointerException
return new File(CLASS_LOADER.getResource(relativePath).getFile());
}
}
folder setup:
root/
src/
foo/
bar/
res/
img/
img1.png
audio/
audio1.wav
The problem arises when I try to execute the jar executable itself. However, the strange thing is that I was not able to replicate this through eclipse IDE which was actually able to resolve the path correctly. I have added the resource directory to the build path via (Project -> Properties -> Java Build Path -> Add Folder) so Java should be able to find the resource folder at runtime.
Is there something I'm missing in terms of generating the jar file? When unpacking the jar file everything seems to be in order with the img and audio directories being in the root (given the above initial folder setup):
foo/
/bar
img/
img1.png
audio/
audio1.wav
Files can only be used to represent actual files in your filesystem. And once you package your files into a JAR, the resource (img/img1.png) is not a file anymore, but an entry in the JAR file. As long as you use the folder structure from within Eclipse, the resources are individual files so everything is fine.
Try this:
System.out.println(CLASS_LOADER.getResource(relativePath));
It will print a URL, but it will not be a valid path to a file in your file system, but to an entry within the JAR file.
Usually, you will only want to read a resource. In that case, use getResourceAsStream() to open an InputStream.

How to get the path of a file in my java project when running java from batch file?

I have a Java 8 application running on Windows. I would like to locate a file in my Java project without using the absolute path. The following code works when I run my application from a command prompt: System.getProperty("user.dir"). However, when I run my java application from a batch file, this code return the path of the batch file, which is not the same as the path of the java application.
How do I get the path of file abc.txt that is located in a folder in my Java project?
System.getProperty("user.dir") got you the right directory because your application was started in the batch file. It's the way it works.
You can always load your files in your application by using a ClassLoader.
Say you have put abc.txt inside your project folder. Actually, if you're using it somewhere in your code as a resource file, you should put it in src/resources folder of your project. Then in your code, do things as below:
File file = new File(getClass().getResource("abc.txt").getFile());
That will give you access to the file no matter where your application starts.
Taking a look at this post on using ClassLoader will help you get a better sense on how to load resources in Java.
UPDATE
, abc.txt is under src folder, which is in the class path.
The MyClass.java only contains below code:
public class MyClass {
public static void main(String[] args) {
System.out.println("s: " + MyClass.class.getClassLoader().getResource("abc.txt").getFile());
}
}
I had the same problem and the only work around I found after searching A LOT was locating the starter Batch file in the same path as the java application, then generate a shortcut of the batch and this is what I could place anywhere in other folders....
After that, the java was running fine...
Assuming that you basically want to have relative paths in your code, You can use the below function to get the source directory and then get any file using the relative location of the file within your source code path.
public static String getMySourcePath() {
URL location = <Your class>.class.getProtectionDomain().getCodeSource()
.getLocation();
String srcPath = location.toString().replace("file:/", "")
.replace("bin", "src");
return srcPath;
}

How do I get the relative path of files in my project?

I am creating a project using jsp/servlet in which I am trying to create java file and class file inside the project itself. But I am able to do this for only my system because the path I give their is like : C:\Users\MySystem\Desktop\Test\.. which works only for my system. What should I do so that if I have to run this project in another system I don't have to change path again and again.
Well if it is maven project just put your resources files under src/main/resources
and you can read them using this lines.
String path = Thread.currentThread().getContextClassLoader()
.getResource("yourFileName").getPath();
System.out.println(path);
Or even this way you can do it.
String pathOfTheFile = getServletContext().getResource("yourFile").getPath();
and don't forget to put the file under web-content or webapp folder

ClassName.class.getResourceAsStream returning Null

I migrated project from Eclipse to Android Studio.
App compiles fine, but it has a crash related to nekohtml library.
Inside HTMLEntities class
//filename = "res/HTMLlat1.properties"
final InputStream stream = HTMLEntities.class.getResourceAsStream(filename);
stream is always null. I tried to move file to the same folder as class and gave full path like this
filename = "/org/cyberneko/html/res/HTMLlat1.properties"
Any ideas?
You should use filename = "/org/cyberneko/html/res/HTMLlat1.properties" instead of filename = "/org.cyberneko.html/res/HTMLlat1.properties" or use relative paths. This could be explained in this way: jar (jar is an example, maybe you're running your code from *.class in some directory) is just some kind of file system with it's root ("/") and all the files in the packages are in some subdirectories and you should specify the paths for them.

How to get the path of a directory where my running jar file is?

I try to retrive a path of a directory where my executable jar file is situated.
That means: I have the following structure:
--> Application (this is a folder somewhere in my file system)
--> application.jar (this is my java application
--> SomeData (folder in the same directory like the application)
--> some other folders
......
When I start my application.jar via command line I want to parse some files inside the SomeData folder.
In https://stackoverflow.com/a/320595/1540630 they already showed how to get the current path of a running jar file but when I execute the statement:
System.out.println(XMLParser.class.getProtectionDomain().getCodeSource().getLocation().getPath());
...I just get the following:
/.../Application/application.jar
But I just want to have:
/.../Application/
Better to say in later steps I need
/.../Application/SomeData/SomeFolder/data.xml
Can someone help me please?
CodeSource.getLocation() gives you a URL, you can then create new URLs relative to that:
URL jarLocation = XMLParser.class.getProtectionDomain().getCodeSource().getLocation();
URL dataXML = new URL(jarLocation, "SomeData/SomeFolder/data.xml");
You can't simply do new File(...getCodeSource().getLocation().getPath()) as a URL path is not guaranteed to be a valid native file path on all platforms. You're much safer sticking with URLs and passing the URL directly to your XML parser if you can, but if you really need a java.io.File then you can use an idiom like this to create one from a URL.
Once you have the jar's location you can use
new File(new File(jarPath).getParent(), "SomeData/SomeFolder/data.xml");
Since you already have the path as a string. You can try the following
String path = XMLParser.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String parentFolder = new File(path).getParent();

Categories