Using PrintWriter for file IO - java

Ok so I'm about to start pulling my hair out. I thought file input was a little tricky, but oh man then there is file output. I am trying to write an array of coordinates stored in an object to a file. In C++ this was easy peasy, but for the love of God I cannot figure this out.
public static void outFile(int intersectionsIndex, Coordinate arg[], Coordinate avgPoint) {
File file = new File("resource/result.txt");
file.getParentFile().mkdirs();
PrintWriter writer = new PrintWriter(file);
int i = 0;
while (i < intersectionsIndex) {
writer.print(arg[i].getX());
writer.print(" ");
writer.println(arg[i].getY());
i++;
}
writer.print("Predicted Coordinate: ");
writer.print(avgPoint.getX());
writer.print(" ");
writer.println(avgPoint.getY());
writer.close();
return;
}
I am constantly getting the same error no matter what method of IO I use. I followed some posts on here with similar problems but to no avail. Any suggestions or other methods? I am probably missing something basic.
Edit: sorry error is
Error:(83, 30) java: unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown
Which is the "PrintWriter writer = newPrintWriter(file); line.
UPDATE: Problem solved. Working code below:
public static void outFile(int intersectionsIndex, Coordinate arg[], Coordinate avgPoint) throws Exception{
File file = new File("resource/result.txt");
file.getParentFile().mkdirs();
PrintWriter writer = new PrintWriter(file);
int i = 0;
while (i < intersectionsIndex) {
writer.print(arg[i].getX());
writer.print(" ");
writer.println(arg[i].getY());
i++;
}
writer.print("Predicted Coordinate: ");
writer.print(avgPoint.getX());
writer.print(" ");
writer.println(avgPoint.getY());
writer.close();
return;
}

It looks like the error that you get is actually a compile-time error, not a runtime error.
The contructor PrintWriter(File) declares a checked FileNotFoundException in its signature, therefore you either need to surround its invocation with try ... catch block, or to declare that exception in throws declaration of your method to catch it later.
See also:
Lesson: Exceptions

Always try to avoid absolute path because the same code might not work on another system.
I suggest you to place it inside the project under resources folder.
You can try any one based on file location.
// Read from resources folder parallel to src in your project
File file1 = new File("resources/results.txt");
// Read from src/resources folder
File file2 = new File(getClass().getResource("/resources/results.txt").toURI());
You might forget to increment i in while loop. Add i++ to avoid infinite loop.
Try
while (i++ < intersectionsIndex) {...}
OR
while (i < intersectionsIndex) {
...
i++;
}

Related

NullPointerException when trying to read file, same exact code worked before [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed last month.
I wanted to run a Java program I wrote two years ago. It needs two files as command line parameters and reads them. This program has worked great before and as it was a school project it went through many tests to make sure everything was working correctly. I downloaded the project from my submission to make sure I had the same version. Only thing this version lacked was the files to read because we were asked not to include them and rather use a path so they don't accidentally get tracked by version control. I added the files to the same directory as the main java file. When I run the program I get:
Welcome to "Name of school project"
Exception in thread "main" java.lang.NullPointerException
at practice.collection.Collection.download(Collection.java:100)
at practice.UI.UI.mainLoop(UI.java:63)
at mainFile.main(mainFile.java:60)
This is what download method in Collection looks like:
public void download(String fileName) {
Scanner fileReader = null;
try {
File file = new File(fileName);
fileReader = new Scanner(file);
while (fileReader.hasNextLine()) {
***reads lines and does some sorting***
}
fileReader.close();
}
catch (FileNotFoundException | NumberFormatException e) {
fileReader.close(); ***this is line 100***
System.out.println("Missing file!");
System.out.println("Program terminated.");
System.exit(0);
}
}
I have also made sure the files to be downloaded are the same as before, they are not empty and are being called with correct spelling, in correct order. Like this: java mainFile first_file.txt second_file.txt. Why is the program not finding the files like before?
I did check out What is a NullPointerException, and how do I fix it? but does not answer my question. I assume I get the exception because my program can't find the file and is thus referring to a file object with null value. I am trying to figure out why the file can't be found and read. I think I should be able to fix this problem without touching the code. The program behaves the same way regardless of if the files have been included.
Suggested changes for troubleshooting the underlying problem:
public void download(String fileName) {
System.out.println("fileName=" + fileName + "...");
System.out.println("current directory=" + System.getProperty("user.dir"));
Scanner fileReader = null;
try {
File file = new File(fileName);
fileReader = new Scanner(file);
while (fileReader.hasNextLine()) {
***reads lines and does some sorting***
}
fileReader.close();
}
catch (FileNotFoundException | NumberFormatException e) {
System.out.println(e); // Better to print the entire exception
//System.out.println("Missing file!"); // Q: What about NumberFormatException?
System.out.println("Program terminated.");
System.exit(0);
}
finally {
// This assumes your app won't be using the scanner again
if (fileReader != null)
fileReader.close();
}
}

reading variables buried in java exception handling

I am writing a function to take a text file and count how many lines it has while outputting the lines to an array of strings. Doing this I have several exceptions I need to look out for. The class function has several variables that should have a scope throughout the function but when I write a value to the function inside of an exception, the return statement cannot find it. I've moved the declaration around and nothing helps
The value returned "h5Files" "Might not have been initialized" Since I don't know how long the array will be I cannot initialize it to a certain length. I do this within the code and I need a way to tell the return statement that I now have a values
Here is the code
public String[] ReadScanlist(String fileIn){
int i;
String directory ="c:\\data\\"; // "\" is an illegal character
System.out.println(directory);
int linereader = 0;
String h5Files[];
File fileToRead = new File(directory + fileIn);
System.out.println(fileToRead);
try {
FileInputStream fin = new FileInputStream(fileToRead); // open this file
}
catch(FileNotFoundException exc) {
System.out.println("File Not Found");
}
try{
//read bytes until EOF is detected
do {
FileReader fr = new FileReader(fileToRead);// Need to convert to reader
LineNumberReader lineToRead = new LineNumberReader(fr); // Use line number reader class
//
while (lineToRead.readLine() != null){
linereader++;
}
linereader = 0;
lineToRead.setLineNumber(0); //reset line number
h5Files = new String[linereader];
while (lineToRead.readLine() != null){
h5Files[linereader] = lineToRead.readLine(); // deposit string into array
linereader++;
}
return h5Files;
}
while(i !=-1); // When i = -1 the end of the file has been reached
}
catch(IOException exc) {
System.out.println("Error reading file.");
}
try{
FileInputStream fin = new FileInputStream(fileToRead);
fin.close(); // close the file
}
catch(IOException exc) {
System.out.println("Error Closing File");
}
return h5Files;
}
Your code is very very odd. For example these two blocks make no sense:
try {
FileInputStream fin = new FileInputStream(fileToRead); // open this file
}
catch(FileNotFoundException exc) {
System.out.println("File Not Found");
}
try{
FileInputStream fin = new FileInputStream(fileToRead);
fin.close(); // close the file
}
catch(IOException exc) {
System.out.println("Error Closing File");
}
I don't know what you think they do, but besides the first one leaking memory, they do nothing at all. The comments are more worrying, they suggest that you need to do more reading on IO in Java.
Deleting those blocks and tidying the code a (moving declarations, formatting) gives this:
public String[] ReadScanlist(String fileIn) {
String directory = "c:\\data\\";
String h5Files[];
File fileToRead = new File(directory + fileIn);
try {
int i = 0;
do {
FileReader fr = new FileReader(fileToRead);
LineNumberReader lineToRead = new LineNumberReader(fr);
int linereader = 0;
while (lineToRead.readLine() != null) {
linereader++;
}
linereader = 0;
lineToRead.setLineNumber(0);
h5Files = new String[linereader];
while (lineToRead.readLine() != null) {
h5Files[linereader] = lineToRead.readLine();
linereader++;
}
return h5Files;
} while (i != -1);
} catch (IOException exc) {
System.out.println("Error reading file.");
}
return h5Files;
}
My first bone of contention is the File related code. First, File abstracts from the underlying OS, so using / is absolutely fine. Second, there is a reason File has a File, String constructor, this code should read:
File directory = new File("c:/data");
File fileToRead = new File(directory, fileIn);
But it should really be using the new Path API anyway (see below).
So, you declare h5Files[]. You then proceed to read the whole file to count the lines. You then assign h5Files[] to an array of the correct size. Finally you fill the array.
If you have an error anywhere before you assign h5Files[] you have not initialised it and therefore cannot return it. This is what the compiler is telling you.
I don't know what i does in this code, it is assigned to 0 at the top and then never reassigned. This is an infinite loop.
So, you need to rethink your logic. I would recommend throwing an IOException if you cannot read the file. Never return null - this is an anti-pattern and leads to all those thousands of null checks in your code. If you never return null you will never have to check for it.
May I suggest the following alternative code:
If you are on Java 7:
public String[] ReadScanlist(String fileIn) throws IOException {
final Path root = Paths.get("C:/data");
final List<String> lines = Files.readAllLines(root.resolve(fileIn), StandardCharsets.UTF_8);
return lines.toArray(new String[lines.size()]);
}
Or, if you have Java 8:
public String[] ReadScanlist(String fileIn) throws IOException {
final Path root = Paths.get("C:/data");
try (final Stream<String> lines = Files.lines(root.resolve(fileIn), StandardCharsets.UTF_8)) {
return lines.toArray(String[]::new);
}
}
Since I don't know how long the array will be I cannot initialize it
to a certain length.
I don't think an array is the correct solution for you then - not to say it can't be done, but you would be re-inventing the wheel.
I would suggest you use a LinkedList instead, something like:
LinkedList<String> h5Files = new LinkedList<>();
h5Files.add(lineToRead.readLine());
Alternatively you could re-invent the wheel by setting the array to an arbritary value, say 10, and then re-size it whenever it gets full, something like this:
h5Files = new String[10];
if (linereader = h5Files.size())
{
String[] temp = h5Files;
h5Files = new String[2 * linereader];
for (int i = 0; i < linereader; i++)
{
h5Files[i] = temp[i];
}
}
Either one of these solutions would allow you to initialize the array (or array alternative) in a safe constructor, prior to your try block, such that you can access it if any exceptions are thrown
Here is your problem. Please take a look on digested version of your code with my comments.
String h5Files[]; // here you define the variable. It still is not initialized.
try{
..................
do {
h5Files = new String[linereader]; // here you initialize the variable
} while(i !=-1); // When i = -1 the end of the file has been reached
..................
catch(IOException exc) {
// if you are here the variable is still not initialized
System.out.println("Error reading file.");
}
// you continue reading file even if exception was thrown while opening the file
I think that now the problem is clearer. You try to open the file and count lines. If you succeed you create array. If not (i.e. when exception is thrown) you catch the exception but still continue reading the file. But in this case you array is not initialized.
Now how to fix this?
Actually if you failed to read the file first time you cannot continue. This may happen for example if file does not exist. So, you should either return when first exception is thrown or just do not catch it at all. Indeed there is nothing to do with the file if exception was thrown at any phase. Exception is not return code. This is the reason that exceptions exist.
So, just do not catch exceptions at all. Declare your method as throws IOException and remove all try/catch blocks.

What is the best way to handle an exception for an invalid file?

I have a java class where a user provides a file path and if the path doesn't exist I ask them to try again. My professor says we should use an exception to handle this.
Here is a snippet of how I'm currently doing it:
public class SalesUtil {
public static void processSales() {
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter sales file name: ");
String salesFile = keyboard.nextLine();
try {
Scanner scanFile = new Scanner(new File(salesFile));
//do stuff
}
} catch(FileNotFoundException fnfe) {
System.out.println("Invalid file name supplied, please try again.");
processSales();
}
}
}
Well in the do stuff section, I'm calculating values and printing data to the console. If I enter the correct file name correctly on the first try all the data is correct. If it is incorrect one or more times the data is not correct.
I imagine this is because of adding function calls on top of my initial stack and never 'getting out' of the initial stack while supplying subsequent stack calls until the correct file is supplied?
I'm still new to java and would appreciate some tips in understanding how to solve this using an exception.
The FileNotFoundException is the correct one to catch, however I gather that you're worried about the stacks building up? I tested reading back the file after multiple failed attempts and it was fine. The recursive call is at the end of the method so it is the last line of code and therefore the stacks shouldn't have any effect.
However, if you want, you could use a while loop instead of recursion to avoid stack buildup:
public static void processSales() {
Scanner scanFile = null;
Scanner keyboard = new Scanner(System.in);
while (scanFile == null) {
System.out.println("Enter sales file name: ");
String salesFile = keyboard.nextLine();
try {
scanFile = new Scanner(new File(salesFile));
while (scanFile.hasNextLine()) {
System.out.println(scanFile.nextLine());
}
} catch(FileNotFoundException fnfe) {
System.out.println("Invalid file name supplied, please try again.");
}
}
}
use the file.exist() method to check, if that what you want to do is to make sure it exist then this is the codes:
File sfile = new File(salesFile);
if (sfile.exists()) {
// ok, file exist do something.
...
}
On the other hand, when you say "invalid file" could be anything, if it is bad filename, then it is another animal (well, different exeception)...
To use try/catch for a readonly file then:
try {
FileInputStream sfile = new FileInputStream(salesFile);
...
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
}

Check if file exists from string

This is the code I use when I try to read some specific text in a *.txt file:
public void readFromFile(String filename, JTable table) {
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader(filename));
String a,b,c,d;
for(int i=0; i<3; i++)
{
a = bufferedReader.readLine();
b = bufferedReader.readLine();
c = bufferedReader.readLine();
d = bufferedReader.readLine();
table.setValueAt(a, i, 0);
table.setValueAt(b, i, 1);
table.setValueAt(c, i, 2);
table.setValueAt(d, i, 3);
}
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
//Close the reader
try {
if (bufferedReader != null) {
bufferedReader.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
And it is called in this way:
readFromFile("C:/data/datafile.txt", table1)
The problem is the following: the 1st time I open the program the *.txt file I'm going to read does not exist, so I thought I could use the function exists(). I have no idea about what to do, but I tried this:
if(("C:/data/datafile.txt").exists()) {
readFromFile("C:/data/datafile.txt", table1)
}
It is not working because NetBeans gives me a lot of errors. How could I fix this?
String has no method named exists() (and even if it did it would not do what you require), which will be the cause of the errors reported by the IDE.
Create an instance of File and invoke exists() on the File instance:
if (new File("C:/data/datafile.txt").exists())
{
}
Note: This answer use classes that aren't available on a version less than Java 7.
The method exists() for the object String doesn't exist. See the String documentation for more information. If you want to check if a file exist base on a path you should use Path with Files to verify the existence of the file.
Path file = Paths.get("C:/data/datafile.txt");
if(Files.exists(file)){
//your code here
}
Some tutorial about the Path class : Oracle tutorial
And a blog post about How to manipulate files in Java 7
Suggestion for your code:
I'll point to you the tutorial about try-with-resources as it could be useful to you. I also want to bring your attention on Files#readAllLines as it could help you reduce the code for the reading operation. Based on this method you could use a for-each loop to add all the lines of the file on your JTable.
you can use this code to check if the file exist
Using java.io.File
File f = new File(filePathString);
if(f.exists()) { /* do something */ }
You need to give it an actual File object. You're on the right track, but NetBeans (and java, for that matter) has no idea what '("C:/data/datafile.txt")' is.
What you probably wanted to do there was create a java.io.File object using that string as the argument, like so:
File file = new File ("C:/data/datafile.txt");
if (file.exists()) {
readFromFile("C:/data/datafile.txt", table1);
}
Also, you were missing a semicolon at the end of the readFromFile call. Im not sure if that is just a typo, but you'll want to check on that as well.
If you know you're only ever using this File object just to check existence, you could also do:
if (new File("C:/data/datafile.txt").exists()) {
readFromFile("C:/data/datafile.txt", table1);
}
If you want to ensure that you can read from the file, it might even be appropriate to use:
if(new File("C:/data/datafile.txt").canRead()){
...
}
as a condition, in order to verify that the file exists and you have sufficient permissions to read from the file.
Link to canRead() javadoc

How to loop a try catch statement?

How do you loop a try/catch statement? I'm making a program that is reading in a file using a Scanner and it's reading it from the keyboard. So what I want is if the file does not exist, the program will say "This file does not exist please try again." then have the user type in a different file name. I have tried a couple different ways to try an do this but, all of my attempts end up with the program crashing.
Here is what I have
try {
System.out.println("Please enter the name of the file: ");
Scanner in = new Scanner(System.in);
File file = new File(in.next());
Scanner scan = new Scanner(file);
} catch (Exception e) {
e.printStackTrace();
System.out.println("File does not exist please try again. ");
}
If you want to retry after a failure, you need to put that code inside a loop; e.g. something like this:
boolean done = false;
while (!done) {
try {
...
done = true;
} catch (...) {
}
}
(A do-while is a slightly more elegant solution.)
However, it is BAD PRACTICE to catch Exception in this context. It will catch not only the exceptions that you are expecting to happen (e.g. IOException), but also unexpected ones, like NullPointerException and so on that are symptoms of a bug in your program.
Best practice is to catch the exceptions that you are expecting (and can handle), and allow any others to propagate. In your particular case, catching FileNotFoundException is sufficient. (That is what the Scanner(File) constructor declares.) If you weren't using a Scanner for your input, you might need to catch IOException instead.
I must correct a serious mistake in the top-voted answer.
do {
....
} while (!file.exists());
This is incorrect because testing that the file exists is not sufficient:
the file might exist but the user doesn't have permission to read it,
the file might exist but be a directory,
the file might exist but be unopenable due to hard disc error, or similar
the file might be deleted/unlinked/renamed between the exists() test succeeding and the subsequent attempt to open it.
Note that:
File.exists() ONLY tests that a file system object exists with the specified path, not that it is actually a file, or that the user has read or write access to it.
There is no way to test if an I/O operation is going to fail due to an hard disc errors, network drive errors and so on.
There is no solution to the open vs deleted/unlinked/renamed race condition. While it is rare in normal usage, this kind of bug can be targeted if the file in question is security critical.
The correct approach is to simply attempt to open the file, and catch and handle the IOException if it happens. It is simpler and more robust, and probably faster. And for those who would say that exceptions should not be used for "normal flow control", this isn't normal flow control ...
Instead of using a try catch block, try a do while loop checking if the file exists.
do {
} while ( !file.exists() );
This method is in java.io.File
You can simply wrap it in a loop:
while(...){
try{
} catch(Exception e) {
}
}
However, catching every exception and just assuming that it is due to the file not existing is probably not the best way of going about that.
Try something like this:
boolean success = false;
while (!success)
{
try {
System.out.println("Please enter the name of the file: ");
Scanner in = new Scanner(System.in);
File file = new File(in.next());
Scanner scan = new Scanner(file);
success = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("File does not exist please try again. ");
}
}
Check if the file exists using the API.
String filename = "";
while(!(new File(filename)).exists())
{
if(!filename.equals("")) System.out.println("This file does not exist.");
System.out.println("Please enter the name of the file: ");
Scanner in = new Scanner(System.in);
filename = new String(in.next();
}
File file = new File(filename);
Scanner scan = new Scanner(file);

Categories

Resources