Reading text file works in IDE but not in .jar - java

I am using
File file = new File("res/movies.txt");
to read text from a bundled .txt file. My code works perfectly when running the program within IntelliJ IDEA, but when I create a .jar file and run it, it gives a "File not found" error. What can I do to make the code work both in the IDE as well as in the jar file?

You need to load the file as a resource. You can use Class.getResourceAsStream or ClassLoader.getResourceAsStream; each will give return an InputStream for the resource.
Once you've got an InputStream, wrap it in an InputStreamReader (specifying the appropriate encoding) to read text from it.
If you need to sometimes read from an arbitrary file and sometimes read from a resource, it's probably best to use separate paths to either create a FileInputStream for the file or one of the methods above for a resource, then do everything else the same way after that.
Here's an example which prints each line from resources/names.txt which should be bundled in the same jar file as the code:
package example;
import java.io.*;
import java.nio.charset.*;
public class Test {
public static void main(String[] args) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
Test.class.getResourceAsStream("/resources/names.txt"),
StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
}

try to change
File file = new File("res/movies.txt");
to
File file = new File("res/movies.jar");
this of course assumes the filename is movies.jar

Related

Java combining two text files

I have an assignment for my Java class which asks me to combine two text files.
This is the code I have up until now.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
public class CombineTwoFile {
public static void main(String[] args) throws IOException
{
ArrayList<String> list = new ArrayList<String>();
try
{
BufferedReader br = new BufferedReader(new FileReader( "A.txt"));
BufferedReader r = new BufferedReader(new FileReader( "B.txt"));
String s1 =null;
String s2 = null;
while ((s1 = br.readLine()) != null)
{
list.add(s1);
}
while((s2 = r.readLine()) != null)
{
list.add(s2);
}
}
catch (IOException e)
{
e.printStackTrace();
}
BufferedWriter writer=null;
writer = new BufferedWriter(new FileWriter("B.txt"));
String listWord;
for (int i = 0; i< list.size(); i++)
{
listWord = list.get(i);
writer.write(listWord);
writer.write("\n");
}
System.out.println("completed");
writer.close();
}
}
Now, when I compile it, i receive this message.
java.io.FileNotFoundException: A.txt (No such file or directory)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.<init>(FileInputStream.java:120)
at java.io.FileInputStream.<init>(FileInputStream.java:79)
at java.io.FileReader.<init>(FileReader.java:41)
at CombineTwoFile.main(CombineTwoFile.java:15)
completed
I am using Coderunner on an Apple computer and i thought perhaps writing the text files as "C:/Users/dell/Desktop/Test/input1.txt" may fix the problem, however i am unsure on how to write that to correspond to my hard drive. Thanks for taking a look and i appreciate any help.
There are several things that could be improved here.
First, as others have pointed out, you need to specify the correct path to the file, the way you're doing it assumes that the files are in the classpath, and apparently they are not.
You can either specify the absolute path, or the relative path compared to the class.
If you want to leave it as is, you're gonna need to put the file in the classpath (where your class runs).
See this for additional info on absolute and relative path:
http://www.xyzws.com/javafaq/what-is-the-difference-between-absolute-relative-and-canonical-path-of-file-or-directory/60
Other than that, you shouldn't be throwing an Exception from main, instead, you should handle it.
I also suggest you use the new try-with-resources.
Example:
try(BufferedReader bf = new BufferedReader(new FileReader( "C:\\Users\\...\\A.txt"));){
//do something
} catch(IOException e){
//handle
}
//no need to close the streams, the jgc will handle that for you
This will close the streams for you when you're done using them, inside of the try block.
If your teacher (as you added in one comment) wants you to be able to dynamically select a path, you're gonna need to enter it from the console and use that as an absolute path.
Scanner s = new Scanner(System.in);
String path = s.readLine(); //use this as absolute path
If you need to do it from a GUI, you're gonna need a JFileChooser.
As far as writing goes, the same suggestions apply.
You could also avoid writing line + '\n' by using a PrintWriter.
It will provide a println(String s) method, auto-flush, and it's better for portability reasons.
As a minor note, in this case you do not actually need s2, using s1 again would do just fine.
Your Java program could not find 'A.txt' at desired location, to know where to put you file you can use system.getproperty( user.dir ) to know where system is looking for file. Other way is you can write absolute path in new File('c:\\something\\A.txt');
Hope it helps
Lucas, your program is absolutely right. you don't need to correct anything just create a file "A.txt" manually, then run this code again.
just place
System.out.println(new File("A.txt").getCanonicalPath());
before
BufferedReader br = new BufferedReader(new FileReader( "A.txt"));
BufferedReader r = new BufferedReader(new FileReader( "B.txt"));
you will get the exact path before the exception information like:
C:\Users\PiyushMittal\Downloads\Java-mongodb-hello-world-example\mongodb\A.txt
java.io.FileNotFoundException: A.txt (The system cannot find the file specified)
completed at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at java.io.FileReader.<init>(FileReader.java:58)
at com.mkyong.core.CombineTwoFile.main(CombineTwoFile.java:19)
and very first line is the place where you have to put the file :)

Java FileNotFoundException although file is there

I set up the method to try/catch this error. My issue is that it catches the fileNotFoundException for Trivia.txt even when I explicitly created Trivia.txt in the same package. I can't figure out why the file is not being found. I did some looking around for the answer to my problem, and had no luck. Anyway, here's my code
public static void readFile(){
try{
File file = new File("Trivia.txt");
FileReader fr = new FileReader(file);
BufferedReader br = new BufferedReader(fr);
while((line = br.readLine()) != null){
System.out.println(line);
}
br.close();
}
catch(FileNotFoundException e){
System.out.println("file not found");
System.out.println();
}
catch(IOException e){
System.out.println("error reading file");
}
}
The code here is just a method of the TextHandler class that is called statically by WindowComp class (totally unrelated class). The package is mainPackage which holds the main() and WindowComp() and textHandler() alond with Triva.Txt
The way you open the file, it's supposed to be found in the current working directory, not in the subdirectory your source is found.
Try System.out.println(file.getCanonicalPath()) in order to find out where the code is expecting the file.
Try loading your file as a Resource, like this
URL fileURL = this.getClass().getResource("Trivia.txt");
File file = new File(fileURL.getPath());
This will load your file from the same package of the class who loads the resource.
You can also provide an absolute path for your file, using
URL fileURL = this.getClass().getResource("/my/package/to/Trivia.txt");
If the file is found somewhere away from the current package of the class, you can also provide an absolute path directly to the constructor:
File file = new File("path/to/file/Trivia.txt");
You can also use a different constructor such as the one indicated in this answer:
Java - creating new file, how do I specify the directory with a method?
For further information, there's always the documentation:
https://docs.oracle.com/javase/7/docs/api/java/io/File.html

How to deploy files in JAR?

I have some method which read some data from the file (actually, it is the bus time).
public void readData(String number) throws IOException{
InputStream fis;
BufferedReader br;
String line;
fis = new FileInputStream("n" + number);
br = new BufferedReader(new InputStreamReader(fis, Charset.forName("UTF-8")));
while ((line = br.readLine()) != null) {
list.add(new Time(line));
}
br.close();
}
And I have my files into project with needed info.
But! (I am writing in Intellij IDEA, but deploying in Eclipse)
When I deploy project, my program doesn't see the files.
What should I do?
Is thinking about
fis = RaspFrame.class.getClassLoader().getResourceAsStream("n" + number);
Right?
"Is thinking about:
fis = RaspFrame.class.getClassLoader().getResourceAsStream("n" + number);
correct?"
Yes. That is (roughly speaking) the way to open a stream to a resource held in a JAR file on your classpath.
(Your existing code is actually reading the files from the file system. It is presumably working from within your IDE because copies of the files are held in the IDE project directory, and the IDE is making the project directory is the "current directory" when you run the program.)

BuferredReader problems

I am having trouble reading from a file. Here is my code can anyone show me where I am wrong?
public static Map<Route, List<Service>> read(String fileName)
throws IOException, FormatException {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String strLine;
while((strLine = reader.readLine())!= null)
{
/* Own Code */
}
reader.close();
}
I am having a FileNotFound Exception. May this be a the location of my file that is wrong?
You seem to want to use a resource. A resource is not accessed as a file, it is better to use it as a stream.
InputStream resourceStream = MyClass.class.getResourceAsStream(fileName);
BufferedReader myReader = new BufferedReader(new InputStreamReader(resourceStream));
Above code takes the location of your class in account, so you can simply use the fileName as is, without a path, and place the fileName next to your .java file. It will automatically be placed next to the generated .class files and - when packaged - in your .jar file.
Just as owlstead commented keep in appropriate location and try like this
URL url = ClassLoader.getSystemResource(fileName);
br = new BufferedReader(new InputStreamReader(url.openStream()));
i.e keep the file in classes folder or bundle with jar or current working directory etc.

What's the difference between File and FileLoader in Java?

So I have the following code where I should read a Text File (This is just the Main Class):
import gui.MenuWindow;
import java.io.IOException;
import javax.swing.JOptionPane;
public class Assessor {
public static void main(String args[]) throws IOException {
FileLoader file = new FileLoader("Example.txt");
try{
new MenuWindow(file.loader());
} catch(Exception exc) {
JOptionPane.showMessageDialog(null, "Error Reading File");
}
}
}
Then I'd have to load the Text into a ListBox using Swing. The thing is that I've found this new code to read a Text File:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;
public class ReadTextFileExample {
public static void main(String[] args) {
File file = new File("test.txt");
StringBuffer contents = new StringBuffer();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String text = null;
// repeat until all lines is read
while ((text = reader.readLine()) != null) {
contents.append(text)
.append(System.getProperty(
"line.separator"));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
// show file contents here
System.out.println(contents.toString());
}
}
So I'd like to know what is the difference between the following two lines:
FileLoader file = new FileLoader("Example.txt"); //First Code
File file = new File("test.txt"); //Second Code
And... What's the StringBuffer and BufferedReader used to? Thanks!
So I'd like to know what is the difference between the following two lines:
FileLoader file = new FileLoader("Example.txt"); //First Code
File file = new File("test.txt"); //Second Code
The first creates a java.io.FileLoader which Andreas discusses. Since the javadoc says "The constructors of this class assume that the default character encoding and the default byte-buffer size are appropriate", it should never be used.
The second creates a java.io.File which is just a file path with some utility methods that can be used to read directory trees, delete, create, and move files, etc., or it can be used with FileInputStream and other classes to actually access the file contents.
And... What's the StringBuffer and BufferedReader used to? Thanks!
The StringBuffer is used to collect the contents of the file.
The BufferedReader is used to speed up reading of the file. Instead of reading one character at a time, the BufferedReader batches reads using an internal buffer.
This is an exemplary question about learning Java SE, especially regarding the java.io package. I was a bit puzzled in the beginning, but now I am quite sure that you want to compare the FileReader to the File class, which both belong to the same package java.io.
File in the Java SE API:"An abstract representation of file and directory pathnames."In other words, it is there to handle files and directories on the file system within Java. Since Java is an object-oriented language, they made a class for it. Files, i.e. binary and text files, share some attributes in common with directories, as there are: absolute, canonical path and simple name, etc.Of course, File is one of the base classes in the java.io package and many classes like FileReader make use of it for object construction.
FileReader:"Convenience class for reading character files."It comes with a handy constructor that takes a file name or file path as a String. Originally, it was meant to be constructed by a File instance. A Reader instance in general is practical to read text files, in contrast to InputStream, which is used to read binary files. A Reader instance in general is connected to a character set, e.g. "UTF-8" to translate byte to character streams.
Please also have a look at the excellent Java Tutorials provided by Oracle.
I hope the difference between File and FileReader becomes a little clearer. Especially note that there is no I/O, when you instantiate a File instance. To answer your question, the interconnection of the two classes would be:
File file = new File("test.txt"); // 1) Instaniate the file
Reader reader = new FileReader(file); // 2) Instantiate the Reader using the File instance
When you wrap a BufferedReader around a Reader instance, you can read the text file linewise, as:
BufferedReader bufferedReader = new BufferedReader(reader); // 3) Get a "buffered reader" to have access line by line.
StringBuffer comes in, when you want to chain a large number of String objects, since String objects is immutable and string operations like
String s1 = "Star ";
String s2 = "Wars";
s1 = s1 + s2;
are very costly, especially in loops, since at every addition a new String object (left side result) is created, with practically no size limits, apart from the reserved Java VM heap space.
Let me point out that you should better use the StringBuilder class, which is even faster, and is the unsynchronized counter-part of StringBuffer, introduced in the Java 5 release. The feature that StringBuffer is guaranteed to be synchronized among different Thread's is hardly ever used. I never came across it in my whole life as Java programmer.

Categories

Resources