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

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

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.

Getting location of file as string in resource folder

I have completed a program in eclipse and now I would like to export it as a single runnable jar file. The program contains a resource folder with images and text files in it. This is located beneath the source folder.
The res file is not added to the build path however when I run the program in Eclipse it still works.
The thing that is confusing me is that the res file is being saved into the runnable jar file when I export it as I can open the Jar file with WinRar and I see the folder is there with all the objects in it. But when I run the problem it stops at the point that the resource folder is referenced. To add to my confusion when I manually copy and paste the res folder next to where the runnable jar file is saved and run the program it works exactly as it should do.
Now I know this is something to do with how I reference the files in my code. At the moment I have it like this
reader = new LineNumberReader(new FileReader("res/usernames.txt"));
This works exactly how I want and accesses the res folder without any exceptions - in Eclipse and when I move the resource folder next to the Jar file.
I would like it to work normally but without having a folder outside of the Jar file I would like it all encapsulated in one Jar file.
I did a lot of research and what seems to be a common fix - may I add I don't really know how it works but everyone seems to mention it - is to somewhere use:
myClass().getResource()
When I create a new FileReader it needs a String input however when I use myClass().getResource() it returns a resource and not a string. I also don't have a clue how it is meant to reference the resource folder. Should I move the resource folder into the source folder?
Does anyone know how I can reference the resource folder from within the runnable jar file?
Sorry for rambling question I know what I want for my final product but I'm getting confused by the build paths and referencing from within classes and I have searched online for a long time trying to figure it out.
Resources, when you deploy your software, are not deployed as files in a folder. They are packaged as part of the jar of your application. And you access them by retrieving them from inside the jar. The class loader knows how to retrieve stuff from the jar, and therefore you use your class's class loader to get the information.
This means you cannot use things like FileReader on them, or anything else that expects a file. The resources are not files anymore. They are bundles of bytes sitting inside the jar which only the class loader knows how to retrieve.
If the resources are things like images etc., that can be used by java classes that know how to access resource URLs (that is, get the data from the jar when they are given its location in the jar), you can use the ClassLoader.getResource(String) method to get the URL and pass it to the class that handles them.
If you have anything you want to do directly with the data in the resource, which you would usually do by reading it from a file, you can instead use the method ClassLoader.getResourceAsStream(String).
This method returns an InputStream, which you can use like any other InputStream - apply a Reader to it or something like that.
So you can change your code to something like:
InputStream is = myClass().getResourceAsStream("res/usernames.txt");
reader = new LineNumberReader( new InputStreamReader(is) );
Note that I used the getResourceAsStream() method from Class rather than ClassLoader. There is a little difference in the way the two versions look for the resource inside the jar. Please read the relevant documentation for Class and ClassLoader.

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

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.

Setting Path Directory on File Reader

I'm working with text files on Java. On Ubuntu 10.
But, I'm having problems with path dir.
Example:
saveFile("textFile.txt","abc");
This abstract function basically put "abc" on "textFile.txt".
I compile this file, and create a jar file (using NetBeans).
When I run the app, and call saveFile("textFile.txt","abc"), textFile.txt is saved on \home. I don't want this. I want that textFile.txtgo to pathDir inside jar file.
How do I write in this file, this same way?
When reading resources from a JAR file, you cannot use the File API. Instead, you use Class.getResourceAsStream(), like this:
reader = new InputStreamReader(MyClass.class.getResourceAsStream(
"/apathdir/textFile.txt"), "UTF-8");
Note also how the encoding is specified. FileReader does not allow that, which is why it should usually be avoided.
Iwant to know, if fileName =
"textFile.txt", what is the path dir
of this file?
If you only use a bare file name (without giving a directory), the JVM will look for the file in the current directory of the JVM process; that is usually the directory you ran the JVM (the java executable) from.
how do i do to set
/apathdir/textFile.txt?. apathdir is a
directory that is inside jar file.
I tried: fileName = "/apathdir/textFile.txt", but doesn't works.
If you want to load a file from inside a JAR file, you cannot load it using FileReader. You need to use ClassLoader.getSystemResourceAsStream() (or Class.getResourceAsStream). See e.g. this article for an explanation:
http://www.devx.com/tips/Tip/5697

Categories