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
Related
I made a small Java program for academic purposes, its main focus is to read some .txt files and present the information to the user. These files are present in the resources folder, under the src folder.
The program runs as intended when launched from Eclipse.
Using the Launch4j app I was able to successfully create an exe which runs fine and does what's intended, up until I try to read the .txt files I have in the resources folder, which appears not to be able to reach.
I'm guessing that when I launch the exe the run time path would change to where the exe was created, so I created the program in a desktop folder and specified this path in the program, but that doesn't seem to solve the situation.
As an alternative, I moved the .txt files out of the program and once again created the exe in a desktop folder with said .txt files, linked the program to this path and once again it didn't work.
The command used to get the .txt files is:
Files.readAllLines(Paths.get(doc)).get(line)
And doc is simply the path to the intended .txt file.
It's worth noting that I have no previous experience in Java and throughout the development of the program I tried my best to use commands I'd fully understand and to keep it as simple as possible. I hope the solution can be along these lines! I'm very confident this must be a rookie mistake, but I can't seem to find the solution to this specific problem anywhere.
The paths to files in Eclipse are different than the paths to files in an .exe or JAR file.
I will let this other user explain it because I am lazy :p
Rather than trying to address the resource as a File just ask the
ClassLoader to return an InputStream for the resource instead via
getResourceAsStream:
InputStream in = getClass().getResourceAsStream("/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
As long as the file.txt resource is available on the classpath then
this approach will work the same way regardless of whether the
file.txt resource is in a classes/ directory or inside a jar.
The URI is not hierarchical occurs because the URI for a resource
within a jar file is going to look something like this:
file:/example.jar!/file.txt. You cannot read the entries within a jar
(a zip file) like it was a plain old File.
This is explained well by the answers to:
How do I read a resource file from a Java jar file?
Java Jar file: use resource errors: URI is not hierarchical
The original post is here, all credit to its author.
Fixing your URL should let you read from that file when you are using the .exe.
EDITED FOR CORRECTION. Thanks #VGR (see comments) for correcting my mistake.
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"));
I need the URI of a file (which I put in the resources directory). If I use
MyClass.class.getClassLoader().getResource(resource)
I get
java.lang.IllegalArgumentException: URI is not hierarchical
Otherwise, if I use ClassLoader.getSystemResource(resource) it returns null.
Are you loading the file from inside a jar? If so, the OS is unable to form a java File instance from inside a jar. To be able to load it, try open it as a Stream. "filepath" should start with a "/".
MyClass.class.getClass().getResourceAsStream( filepath );
You should be using
getResourceAsStream(...);
when the resource is bundled as a jar/war or any other single file package for that matter.
See the thing is, a jar is a single file (kind of like a zip file) holding lots of files together. From Os's pov, its a single file and if you want to access a part of the file(your image file) you must use it as a stream.
I have a Java application in Eclipse that references .XML files as templates for other functionality. Usually I package the .JAR file without these files, because placing them within the same folder as the .JAR file seems to work fine with this reference:
File myFile = new File("templates/templateA.xsd");
I now require that these templates be placed within the same .JAR file as this application. I can include them with no problems, but these references no longer seem to work.
Is there a correct way of referencing the .XML file from within the same .JAR that the application is running from?
You need to know how to load the files from class path.
one of the ways is as follows
class XMLLoader {
public String loadXML(String fileName){
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileName);
// do the loading of the file from the given input stream.
}
}
you know that the "templates" folder should be inside of your jar.
If you just need to read this file, you might not need a java.io.File but just an InputStream that you can get via
this.getClass().getResourceAsStream("templates/templateA.xsd")
If you really need a java.io.File... I do not know... The last time a really needed a File, I just copied the InputStream to a temporary file but this is ugly.
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