I am writing a small Java Library (say project A) to be used externally (as a .JAR) in any other project (project B).
This is how project A looks like :
projectA
--src/main/java
--packageOne
....
--packageTwo
--A.java // need to access the next few text files in this java file
--ImportantTextOne.txt
--ImportantTextTwo.txt
--ImportantTextThree.txt
This is how project B will look like :
projectB
--src/main/java
--B.java // I will use project A here.
I have tried importing the text files, but every time I use it as a .JAR externally in ProjectB, I always get some errors such as
java.nio.file.NoSuchFileException
I presume this is because of some class path issue.
So how do i correctly read my text files in ProjectA?
thanks in advance
Edit : I don't need the text files in projectB, they are just used once to pull text from in projectA. All I want is to correctly read those files in projectA, so I can import projectA in any project and not get errors.
You placed the txt files besides the class files. You may have to move them to
src/main/resources/packageTwo
for your build process to correctly handle them. Anyway, make sure they are at the right location once the jar file is built.
To access such a file, you cannot load it from the filesystem as it is part of your jar. But it is on the classpath. So you need to access it like
URL url = A.class.getResource("/packageTwo/ImportantTextOne.txt");
// check what url you got - if it is null the resource was not found
InputStream in = url.openStream();
...
So with the help of Hiran's response and digging around (also this) I figured it out.
File structure of the library you are writing :
projectA
--src/main/java
--packageOne
....
--packageTwo
--A.java // need to access the next few text files in this java file
--ImportantTextOne.txt
--ImportantTextTwo.txt
--ImportantTextThree.txt
Whenever reading a file, treat it as a resource. As when the class will be used as an external .JAR you will not be able to access files inside the .JAR. Instead follow this type of pattern :
A.java
URL url = this.getClass().getResource("ImportantTextOne.txt") // this assumes your text file is in the same location as A.java
InputStream in = url.openStream();
String text = new BufferedReader(
new InputStreamReader(in, StandardCharsets.UTF_8))
.lines()
.collect(Collectors.joining("\n"));
Related
When someone opens my jar up I am opening a file selector gui so they can choose where they want to store their jar's files like config files and such. This should only take place the first time they open the jar. However, one issue with this approach is that I would have no way to know if it's their first time opening the jar since I will need to save the selected path somewhere. The best solution to this sounds like saving the selected path inside a file in the resource folder which is what I am having issues with. Reading and writing to this resource file will only need to be done when the program is actually running. These read and write operations need to work for packaged jar files (I use maven) and in the IDE.
I am able to read a resources file inside of the IDE and then save that file to the designated location specified in the file selector by doing this. However, I have not been able to do the same from a jar despite trying multiple other approaches from other threads.
ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("config.yml");
try {
if(is != null) {
Files.copy(is, testFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
So just to clarify when my project is loaded I need to listen for the user to select a valid path for files like my config. Then I want to write my config to that path which I can do from my IDE and is shown above but I cant figure this out when I compile my project into a jar file since I always receive a file not found error in my cmd. However, the main point of this post is so that I can figure out how to save that selected path to my resource folder to a file (it can be json, yml or whatever u like). In the code above I was able to read a file but I have no idea how to go from that to get the files path since then reading and writing to it would be trivial. Also keep in mind I need to be able to read and write to a resource folder from both my IDE and from a compiled jar.
The following code shows my attempt at reading a resource from a compiled jar. When I added a print statement above name.startWith(path) I generated a massive list of classes that reference config.yml but I am not sure which one I need. I assume it has to be one of the paths relating to my project or possible the META-INF or META-INF/MANIFEST.MF path. Either way how am I able to copy the file or copy the contents of the file?
final String path = "resources/config.yml";
final File jarFile = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getPath());
if(jarFile.isFile()) { // Run with JAR file
try {
final JarFile jar = new JarFile(jarFile);
final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
while(entries.hasMoreElements()) {
final String name = entries.nextElement().getName();
if (name.startsWith(path)) { //filter according to the path
System.out.println(name);
}
}
jar.close();
} catch (IOException exception) {
exception.printStackTrace();
}
}
Also if you were wondering I got the above code from the following post and my first block of code I pasted above is actually in the else statement since the IDE code from that post also did not work.
How can I access a folder inside of a resource folder from inside my jar File?
You can't write to files inside your JAR file, because they aren't actually files, they are ZIP entries.
The easiest way to store configuration for a Java application is to use Preferences:
Preferences prefs = Preferences.userNodeForPackage(MyApp.class);
Now all you have to do is use any of the get methods to read, and put methods to write.
There is absolutely no need to write files into your resource folder inside a jar. All you need to have is a smart classloader structure. Either there is a classloader that allows changing jars (how difficult is that to implement?), or you just setup a classpath that contains an empty directory before listing all the involved jars.
As soon as you want to change a resource, just store a file in that directory. When loading the resource next time, it will be searched on the classpath and the first match is returned - in that case your changed file.
Now it could be that your application needs to be started with that modified classpath, and on top of that it needs to be aware which directory was placed first. You could still setup that classloader structure within a launcher application, which then transfers control to the real application loaded via the newly defined classloader.
You could also check on application startup whether a directory such as ${user.home}/${application_name}/data exists.
If not, create it by extracting a predefined zip into this location.
Then just run your application which would load/write all the data in this directory.
No need to read/write to the classpath. No need to include 3rd party APIs. And modifying this initial data set would just mean to distribute a new zip to be extracted from.
i have a small application which checks for values from a file and display the result in a jframe.
A file contain list of word to check. this file is placed in project folder "testing" and the main source testing.java file is present in location "testing\src\testing"
input file : c:\document..\netbeans\testing\
java file : c:\document..\netbeans\testing\src\testing\
when i place the input file inside folder "c:\document..\netbeans\testing\src\testing\
" the input file is not taken as input, it works only when kept on folder "c:\document..\netbeans\testing\"
so when a jar file is created it has not included the input file in that, even i manually input that is not taking the input file in and working.
some path setting issue? what can be done to solve this issue?
any help pls??
Once you create the jar, the file becomes an embedded resource. If you try to read it as a File it will no long be the same file system path as you originally use in the program. It must now be read from the class path.
To read the file from the class path, you will want to use getClass().getResourceAsStream(), which return an InputStream. If your file is in the same location (package) as your class file, then you should use
InputStream is = getClass().getResourceAsStream("input.txt");
Then you can read from the InputStream
BufferedReader reader = new BufferedReader (new InputStreamReader(is));
This generally happens, when you don't use absolute path...!
As when you run your program from IDE(Netbeans) then the HOME_FOLDER is your ProjectFolder. Relative to which you would have given the file_path(that has to be accessed in your program).
But after building, jar is present in ProjectFolder/dist. When you run the jar file the HomeFolder is not ProjectFolder rather it is ProjectFolder/dist.
So, to make it successful, to need to copy all files and folders from ProjectFolder/dist to ProjectFolder.
Then run the jar.. Hope it will fix the issue
Try putting double backslashes in your file paths. Like this:
c:\\document..\\netbeans\\testing\\src\\testing\\
This is the format that java normally requires it to be in
InputStream inp = new FileInputStream("src/main/resources/ExportHour.xls");
I have a file in the src/main/resources folder of my Java Spring project.
I am attempting to create an inputstream in one of my Controllers, however I always get a file not found exception. When I change the path location to point specifically to the file on my machine, it works fine.
Any way I can make it so the file can be found within the java project?
Try with spring ClassPathResource.
InputStream inp = new ClassPathResource("ExportHour.xls").getInputStream();
That is because the resources folder in maven is put in your jar file directly i.e. the ExportHours.xls file is put inside your jar in the root directory.
It sounds like you could just change the working directory of your process - it's not where you think it is, I suspect. For example, I suggest you write
File file = new File("src/main/resources/ExportHour.xls");
and then log file.getAbsolutePath(), to see what exact file it's using.
However, you should almost certainly not be using a FileInputStream anyway. It would be better to use something like:
InputStream inp = Foo.class.getResourceAsStream("/ExportHour.xls");
... for some class Foo which has a classloader which includes the resources you need.
(Or possibly /resources/ExportHour.xls", depending on your build structure.)
That way even when you've built all of this into a jar file, you'll still be able to open the resource.
Been looking for this for the past 2 hours and can't find anything (I've found solutions to the same problem but with images, not text files).
Pretty much, I made a program that reads a text file. The file is a list of names and IDs. Using Eclipse, I put the file in my src folder and in the program put the path file to it. Like this:
in = new BufferedReader(new FileReader(curDir+"\\bin\\items.txt"));
Where curDir is the user's current directory (found with System.getProperty("user.dir")).
Now, problem is, the program runs fine when I run it from Eclipse, but when I try to make it a runnable JAR and then run it, the program runs, but the info from the text file does not load. It look like Eclipse is not putting the text file with the JAR.
EDIT: Solved-ish the problem? So the JAR file needs to the in a folder with all the original files? I am so confused, what is a JAR file then?
A more robust way to get a file whether you are running from Eclipse or a JAR is to do
MyClass.getResource("items.txt")
where MyClass is a class in the same package (folder) as the resource you need.
If Eclipse is not putting the file in your JAR you can go to
Run -> Run Configurations -> -> Classpath tab -> Advanced -> Add Folders
Then add the folder containing your file to the classpath. Alternatively, export the Ant script and create a custom build script.
To the point, the FileReader can only read disk file system resources. But a JAR contains classpath resources only. You need to read it as a classpath resource. You need the ClassLoader for this.
Assuming that Foo is your class in the JAR which needs to read the resource and items.txt is put in the classpath root of the JAR, then you should read it as follows (note: leading slash needed!):
InputStream input = Foo.class.getResourceAsStream("/items.txt");
reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
// ...
Or if you want to be independent from the class or runtime context, then use the context class loader which operates relative to the classpath root (note: no leading slash needed!):
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("items.txt");
reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
// ...
(UTF-8 is of course the charset the file is encoded with, else you may see Mojibake)
Get the location of your jar file
Firstly create a folder(say myfolder) and put your files inside it
Consider the following function
public String path(String filename)
{
URL url1 = getClass().getResource("");
String ur=url1.toString();
ur=ur.substring(9);
String truepath[]=ur.split("myjar.jar!");
truepath[0]=truepath[0]+"myfolder/";
truepath[0]=truepath[0].replaceAll("%20"," ");
return truepath[0]+filename;
}//This method will work on Windows and Linux as well.
//You can alternatively use the following line to get the path of your jar file
//classname.class.getProtectionDomain().getCodeSource().getLocation().getPath();
Suppose your jar file is in D:\Test\dist
Then path() will return /D:/Test/dist/myfolder/filename
Now you can place 'myfolder' inside the folder where your jar file is residing
OR
If you want to access some read-only file inside your jar you should copy it to one
of your packages and can access it as
yourClassname.getResource("/packagename/filename.txt");
I need to read a text file when I start my program. I'm using eclipse and started a new java project. In my project folder I got the "src" folder and the standard "JRE System Library" + staedteliste.txt... I just don't know where to put the text file. I literally tried every folder I could think off....I cannot use a "hard coded" path because the text file needs to be included with my app...
I use the following code to read the file, but I get this error:
Error:java.io.FileNotFoundException:staedteliste.txt(No such file or directory)
public class Test {
ArrayList<String[]> values;
public static void main(String[] args) {
// TODO Auto-generated method stub
URL url = Test.class.getClassLoader().getResource("src/mjb/staedteliste.txt");
System.out.println(url.getPath()); // I get a nullpointerexception here!
loadList();
}
public static void loadList() {
BufferedReader reader;
String zeile = null;
try {
reader = new BufferedReader(new FileReader("src/mjb/staedteliste.txt"));
zeile = reader.readLine();
ArrayList<String[]> values = new ArrayList<String[]>();
while (zeile != null) {
values.add(zeile.split(";"));
zeile = reader.readLine();
}
System.out.println(values.size());
System.out.println(zeile);
} catch (IOException e) {
System.err.println("Error :"+e);
}
}
}
Ask first yourself: Is your file an internal component of your application?
(That usually implies that it's packed inside your JAR, or WAR if it is a web-app; typically, it's some configuration file or static resource, read-only).
If the answer is yes, you don't want to specify an absolute path for the file. But you neither want to access it with a relative path (as your example), because Java assumes that path is relative to the "current directory". Usually the preferred way for this scenario is to load it relatively from the classpath.
Java provides you the classLoader.getResource() method for doing this. And Eclipse (in the normal setup) assumes src/ is to be in the root of your classpath, so that, after compiling, it copies everything to your output directory ( bin/ ), the java files in compiled form ( .class ), the rest as is.
So, for example, if you place your file in src/Files/myfile.txt, it will be copied at compile time to bin/Files/myfile.txt ; and, at runtime, bin/ will be in (the root of) your classpath. So, by calling getResource("/Files/myfile.txt") (in some of its variants) you will be able to read it.
Edited: Further, if your file is conceptually tied to a java class (eg, some com.example.MyClass has a MyClass.cfg associated configuration file), you can use the getResource() method from the class and use a (resource) relative path: MyClass.getResource("MyClass.cfg"). The file then will be searched in the classpath, but with the class package pre-appended. So that, in this scenario, you'll typically place your MyClass.cfg and MyClass.java files in the same directory.
One path to take is to
Add the file you're working with to the classpath
Use the resource loader to locate the file:
URL url = Test.class.getClassLoader().getResource("myfile.txt");
System.out.println(url.getPath());
...
Open it
Suppose you have a project called "TestProject" on Eclipse and your workspace folder is located at E:/eclipse/workspace. When you build an Eclipse project, your classpath is then e:/eclipse/workspace/TestProject. When you try to read "staedteliste.txt", you're trying to access the file at e:/eclipse/workspace/TestProject/staedteliste.txt.
If you want to have a separate folder for your project, then create the Files folder under TestProject and then access the file with (the relative path) /Files/staedteliste.txt. If you put the file under the src folder, then you have to access it using /src/staedteliste.txt. A Files folder inside the src folder would be /src/Files/staedteliste.txt
Instead of using the the relative path you can use the absolute one by adding e:/eclipse/workspace/ at the beginning, but using the relative path is better because you can move the project without worrying about refactoring as long as the project folder structure is the same.
Just create a folder Files under src and put your file there.
This will look like src/Files/myFile.txt
Note:
In your code you need to specify like this Files/myFile.txt
e.g.
getResource("Files/myFile.txt");
So when you build your project and run the .jar file this should be able to work.
Depending on your Java class package name, you're probably 4 or 5 levels down the directory structure.
If your Java class package is, for example, com.stackoverflow.project, then your class is located at src/com/stackoverflow/project.
You can either move up the directory structure with multiple ../, or you can move the text file to the same package as your class. It would be easier to move the text file.
MJB
Please try this
In eclipse "Right click" on the text file u wanna use,
see and copy the complete path stored in HDD like (if in UNIX "/home/sjaisawal/Space-11.4-template/provisioning/devenv/Test/src/testpath/testfile.txt")
put this complete path and try.
if it works then class-path issue else GOK :)
If this is a simple project, you should be able to drag the txt file right into the project folder. Specifically, the "project folder" would be the highest level folder. I tried to do this (for a homework project that I'm doing) by putting the txt file in the src folder, but that didn't work. But finally I figured out to put it in the project file.
A good tutorial for this is http://www.vogella.com/articles/JavaIO/article.html. I used this as an intro to i/o and it helped.
Take a look at this video
All what you have to do is to select your file (assuming it's same simple form of txt file), then drag it to the project in Eclipse and then drop it there. Choose Copy instead of Link as it's more flexible. That's it - I just tried that.
You should probably take a look at the various flavours of getResource in the ClassLoader class: https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ClassLoader.html.