Can't getResourcesAsStream() from a folder (in a jar) - java

I have a problem, I want to list the files in "default" folder, this folder is in the resources folder :
-resources/languages/default/manyfiles
The second line throws a nullPointerException
InputStream in = getClass().getClassLoader().getResourceAsStream("languages/default/");
BufferedReader br = new BufferedReader(new InputStreamReader(in));
It seems I can't do this with a folder but only with a file. The problem is I can't use File because this is inside a jar.
EDIT : here the content of the jar :
http://www.mediafire.com/view/05u5w20xupt1mo1/javapbfolder.bmp

There is no standard way to list the contents of a folder. The reason is that there concept of a file system behind the class resource loading, just names/location of a resource.
It depends what you want to do, how to work around this. Possible solutions come to my mind:
Retrieve the URL from one resource in the directory. Extract the JAR file from the URL and open the JAR via the ZipFile class. This is "hacky" and may or may not work, depending on the platform you run and security settings.
Generate an index file when you pack the JAR that contains the list of the resources.
Put in a JAR into the resource, that you then open via ZipFile.

Related

Java FileNotFoundException when trying to read txt file from resources folder

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

Where do I put files to be read by java.io.FileReader?

I'm using java.io.FileReader:
FileReader fileReader = = new FileReader(filepath)
When running locally, a typical filepath would be
"/Users/acypher/Desktop/enrollment.json"
Then, when I deploy to Tomcat on AWS, I want to put the file somewhere in the build that FileReader can find -- any place is fine with me, but I haven't been able to find any location that works, since I don't know what root directory FileReader is using.
The .war expands to a folder which includes META-INF and WEB-INF subfolders. WEB-INF contains a "classes" folder, which contains files that are locally in my src/main/resources/ folder, so that seems like a good location. But I don't know how to set the filepath to refer to this location.
I'm using IDEA with Spring Boot.
The /src/main/resources/ is definitely the way to go. You can access the files in this folder with the methods Class.getResource(String) or Class.getResourceAsStream(String) (see: https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getResourceAsStream(java.lang.String)).
For example, if you have your file in /src/main/resources/myFolder/myFile.myExt, you can either call:
this.getClass().getResource("myFolder/myFile.myExt")
this.getClass().getResourceAsStream("myFilder/myFile.myExt")
which, in a static context, where you don't have the this reference, become, respectively:
MyClass.class.getResource...
MyClass.class.getResourceAsStream
In the first case you should (I didn't verify it myself) be able to create a File instance like this: File file = new File(this.getClass().getResource("myFolder/myFile.myExt").toURI()), and from that the FileReader instance; while in the second case, you have at your disposal the InputStream which you can use to read the file.

How to read a file from a different folder than the project

I'm trying to read a txt file that is in a folder called "levels". The class where I'm using the Scanner is in src/anotherPackageName, if that's relevant. When I execute:
Scanner s = new Scanner(new File("levels/level0")); //adding .txt doesn't fix
it throws an exception. I don't want to use an absolute path, but rather relative to the project if possible. This is my folder structure:
D:\OneDrive\Folder\AnotherFolder\ProjectName
ProjectName
src
packageOne
ClassWhereImUsingScanner
OtherClasses
(...)
levels
level0
level1
(...)
So in order to access a file you could do something like this:
FileReader sourceFile = new FileReader("levels/level0.txt");
BufferedReader inStream = new BufferedReader(sourceFile);
String Line = inStream.readLine();
Then, you can use a tokenizer depending on your data and how you want to store it.
You could see this example: http://www.mkyong.com/java/how-to-read-file-from-java-bufferedreader-example/
Bear in mind that in most Java code, the end state of the project is not run from the IDE, but rather from some production system (e.g. an app or a server). In that case, your development source code structure won't be available.
There are two main ways to read text files or other resources in Java: either you can find the path to the actual file, in which case you need to deal with possibly not running out of your development source tree, or else you need to find a way to bundle the text file into your project.
Most Java projects end up getting compiled into some kind of archive, either a JAR file or a WAR file (for web applications) or something like an Android APK. In most cases you can add your own text files into the project archive. (For example, in a Maven project, if you just put your text file in the src/main/resources folder it should be included in the compiled JAR.)
However, in this case, the text file is no longer a separate file on disk, but rather a blob of data inside an archive. You could unzip the archive to get an actual File object, but that's wasteful if all you actually need is to read the bytes.
Thus, the most common way that text files like this are read is by using the existing ClassLoader mechanism, which is what is reading the .class files from disk (or from an archive, or over the network, or whatever). The ClassLoader already knows how to load bytes that are "alongside" your compiled code, so you can just make use of that.
In your case, you should be able to do something like this:
Scanner scanner = new Scanner(
getClass().getResourceAsStream("/path/to/file.txt"));
In this case, the /path/to/file.txt path is relative to the path your class was loaded from. E.g. if your class is named my.package.Foo then the actual class bytes will be in a folder (either a filesystem folder or in a JAR file or something) named my/package/Foo.class -- in this case, the path/to/file.txt and my/package/Foo.class will be relative to the same root.
See the documentation on resources for more information.
Usually the path is relative to your execution, but it also depends on your project setup on eclipse, could you send more information about you directory structure?
Based on you structure try something like this:
Scanner s = new Scanner(new File("../levels/level0"));

File cannot be accessed after export (Java)

I know that there are many questions like this out there, but so far there have been none that have been of help.
In eclipse, I have a file inside of my project folder ,and I can get it to load using:
BufferedReader in = new BufferedReader(new FileReader(new File(path)));
When I export the project it will not load the file because it cannot find the file. I have no idea what is going on. Any suggestions? Thanks.
If you want to read the file, you have two options.
You Could...
Make sure that the file is in the same directory as the exported jar file and/or the same execution context. This will allow you to use something like BufferedReader in = new BufferedReader(new FileReader(new File("./" + fileName)));
When referencing the file, it need to specify a relative path to the file.
This means you must ensure that the file is copied to the correct location when ever you move the jar file.
You Could...
Embed the file within the jar as an embedded resource. This means that the file becomes part of the jar file. This also means that you can no longer reference it as a File, but need to use Class#getResource or Class#getResourceAsStream, for example...
BufferedReader in = new BufferedReader(
new InputStreamReader(this.getResourceAsStream("/path/to/resource")));
In order to use this, the file must be placed within the resources directory within your Eclipse project and the directory included within your build path
If you want to be able to write to the file, then you MUST use option one. Embedded resources can not be written to (without a lot of work)

NullPointerException trying to load a file

Scenario is the following:
Developing a jsp application with jdeveloper
Deploying to Oracle Weblogic
All files are in the same project
Source files are inside packages that are inside the src folder
Inside the Resources folder are two files: menu.json and TestWS.properties
So, I made a java class that should read menu.json and return a menu (in html) based on its structure.
When, inside the class, I do this
InputStream i =
Thread.currentThread().getContextClassLoader().
getResourceAsStream("Resources/menu.json");
BufferedReader r = new BufferedReader(new InputStreamReader(i));
The InputStreamReader constructor throws a NullPointerException, I suppose because it can't find the file.
Funny thing is, if I try to load TestWS.properties instead, it loads it just well.
I tried checking the project's properties, manually added both files under Project Source Path -> Resources, adding the .json extension to Compiler -> Copy file types to output directory, renamed, deleted, recreated, changed extension to the json file, deployed to WAR and loaded the project on another machine running weblogic, but to no avail.
Is there anything else I'm missing?
This is explained in this article.
In short, you have to change the compiler setting "Copy File Types to Output Directory" to include the extension of the resources you want to have available at runtime.

Categories