ClassName.class.getResourceAsStream returning Null - java

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.

Related

Why won't input stream find a file outside of the class folder

I want to want to use input stream with a file "NewFile.java", the code I have works fine if the file is situated in the same folder as the .class file that is performing the action. But once I move I get null reference.
I have tried using absolute and relative paths with and without a '/' at the start.
InputStream in = getClass()
.getResourceAsStream("NewFile.java");
I would like to source the file when it is located in the root directory of the project.
Better use InputStream in= new FileInputStream(new File("path/to/yourfile"));
The way you are using it now is as a resource which has to be in the class path.
getResourceAsStream() is not meant to open arbitrary files in the filesystem, but opens resource files located in java packages. So the name "/com/foo/NewFile.java" would look for "NewFile.java" in the package "com.foo". You cannot open a resource file outside a package using this method.
There is a distinction between files on the file system, and resources, on the class path. In general a .java source file won't be copied/added to the class path.
For a class foo.bar.Baz and a resource foo/bar/images/test.png one can use
Baz.class.getResourceAsStream("images/test.png")
Baz.class.getResourceAsStream("/foo/bar/images/test.png")
As you see the paths are class paths, possibly inside .jar files.
Use file system paths:
Path path = Paths.get(".../src/main/java/foo/bar/Baz.java");
InputStream in = Files.newInputStream(path);
List<String> lines = Files.readAllLines(path);
List<String> lines = Files.readAllLines(path, StandardCharsets.ISO_8859_1);
Files.copy(path, ...);

Jar is not loading resources file

I have a project with a folder "src/main/resources" where inside there is the hibernate configuration file, I load it using this line of code
HibernateUtil.class.getResource("/hibernate.cgf.xml").getPath()
From inside the IDE it is working well, but when I create the jar it doesn't file the file.
How can I load it properly in the jar file too?
Thanks
Could you please try this:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("fileName").getFile());
I cannot say for ceratin that this is the issue without knowing how exactly you use the path extracted by:
HibernateUtil.class.getResource("/hibernate.cgf.xml").getPath()
but I can tell you this:
Run from an IDE the above line of code will return:
/path/to/project/src/main/resources/hibernate.cgf.xml
which is a valid filesystem path. You can then use this path to, for example, create an instance of File class and then use that instance to read the file contents.
However the same line of code run from inside a jar file will return:
file:/path/to/jar/jar_name.jar!/hibernate.cgf.xml
which is not a valid filesystem path. If you create an instance of File class using this path and then try to read the contents of the file you'll get an exception: java.io.FileNotFoundExeption
To read the contents of the file from inside of a jar you should use method Class.getResourceAsStream(String), which will return an instance of class sun.net.www.protocol.jar.JarURLConnection.JarURLInputStream (or equivalent in non-Oracle or non-OpenJDK Java). You can then use this object to read the contents of the file. For example:
InputStream inputStream = HibernateUtil.class.getResourceAsStream("/hibernate.cgf.xml");
Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
String fileContents = scanner.hasNext() ? sscanner.next() : "";
Most likely, the file is absent from the jar you create. There's too little information in your question, but I will try a guess:
Your hibernate.cgf.xml resides in the same directory as the Java sourcefles, and you are using a build tool (be it IDE, maven, gradle or an ant script) that expects resources to be stored in a separate directory.
It's easy to check: try to unzip your jar and see if the file is there (use any tool, you can just change the extension from .jar to .zip). I think you will see the file is absent.
Then come back with a question: "how to pack my non-java resources into a jar, using XXX", where XXX will be the name of the techology you are using for building the jar.
Most probably the slash in "/hibernate.cgf.xml" is not needed, if the hibernate.cgf.xml is in the same package as you class HibernateUtil.
You can access the file actually also via the classloader using the full path. Yet you never add to it the first slash.
Here is some code demonstrating how you can access the file using different methods:
public static void main(String[] args) {
// Accessing via class
System.out.println(SimpleTests.class.getResource("hibernate.cgf.xml").getPath());
// Accessing via classloader from the current thread
String path = Thread.currentThread().getContextClassLoader()
.getResource("simple/hibernate.cgf.xml").getPath();
System.out.println(path);
// Accessing via classloader used by the current class
System.out.println(SimpleTests.class.getClassLoader().getResource("simple/hibernate.cgf.xml").getPath());
}
In the example above the package 'simple' should be replaced by the package where your hibernate.cgf.xml is. But you should never have the slash at the beginning of the package declaration.

Using getResourceAsStream is not working in Java [duplicate]

This question already has answers here:
How to read text file from classpath in Java?
(17 answers)
Closed 7 years ago.
I have a very simple method which uses the getclass().getResourceAsStream() method to read a file. However it always returns null and I can't figure out what is wrong. Here is my piece of code.
InputStream sw = getClass().getResourceAsStream("/filename.txt");
BufferedReader bf = new BufferedReader( new InputStreamReader(sw));
sw always remain null. the file filename.txt exist in the root directory of my project.
EDIT:
I found the reason. I realized that I was running my project from Eclipse and the project was not part of the classpath on my PC. However if I package my program as a jar file and then run it, the files in the jar file are considered as resources and can be read using the getResourceAsStream() method.
The method Class.getResourceAsStream() looks for the designated resource within the Java class path, not based on the project root.
The project root usually is not part of the classpath. Instead, you should have a src folder (or a similar name), which contains the Java files and may also contain your text file. Or, if you use Maven, you have folders src/main/java and src/main/resources, which are classpath roots. In this case, the text file should reside in the resources folder.
If your project gets packaged into a .jar file, all its resources are packaged in the .jar file along with the .class files, and will be found by Class.getResourceAsStream().
Root of your project is not always the root of the path from the ClassLoader point of view.
Easiest way to find out where it is trying to load the resource from:
System.out.println(MyClass.class.getResource("/").getPath());
And after that you may be able to easily find out the part of the project or run configuration that causes the difference between your assumption and the reality about the right placement of the file.
getResourceAsStream() reads a resource file, ie a file into .jar file (or resource directory), not a regular file in working directory on disk. Use FileReader to read a file from disk
user likewise,
InputStream sw = this.class.getClassLoader().getResourceAsStream("filename.txt");
Note : filename.txt file should be present on classpath.
Just to be complete, here's a simple test that does print out the absolute path of a resource. You can use this inside any class to find the location of that class on your hard drive, in case it isn't obvious what your build system is doing. Just substitute the name ErrorTest for the class you are checking.
public class ErrorTest
{
public static void main(String[] args )
{
final String className = ErrorTest.class.getSimpleName().replace( '.', '/').concat(".class");
System.out.println(ErrorTest.class.getResource(className).getPath() );
}
}
Output of this program:
run:
/C:/Users/Brenden/Google%20Drive/proj/tempj8/build/classes/quicktest/ErrorTest.class
BUILD SUCCESSFUL (total time: 0 seconds)

Java NIO filesystem

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);

Java JAR: Writing to a file

Currently, in my eclipse project, I have a file that I write to. However, I have exported my project to a JAR file and writing to that directory no longer works. I know I need to treat this file as a classpath resource, but how do I do this with a BufferedWriter?
You shouldn't have to treat it as a classpath resource to write to a file. You would only have to do that if the file was in your JAR file, but you don't want to write to a file contained within your JAR file do you?
You should still be able to create and write to a file but it will probably be relative to the working directory - the directory you execute your JAR file from (unless you use an absolute path). In eclipse, configure the working directory from within the run configuration dialog.
You're probably working in Linux. Because, in Linux, when you start your application from a JAR, the working directory is set to your home folder (/home/yourname/). When you start it from Eclipse, the working directory is set to the project folder.
To make sure you really know the files you are using are located in the project folder, or the folder where your JAR is in, you can use this piece of code to know where the JAR is located, then use the File(File parent, String name) constructor to create your files:
// Find out where the JAR is:
String path = YourClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath();
path = path.substring(0, path.lastIndexOf('/')+1);
// Create the project-folder-file:
File root = new File(path);
And, from now on, you can create all your File's like this:
File myFile = new File(root, "config.xml");
Of course, root has to be in your scope.
Such resources (when altered) are best stored in a sub-directory of user.home. It is a reproducible path that the user should have write access to. You might use the package name of the main class as a basis for the sub-directory. E.G.
our.com.Main -> ${user.home}/our/com/

Categories