File Handling in Java

Java has some confusing classes and syntax for handling files.

In the first part of this tutorial which covers file reading there will be three classes involved and one import. The import you’ll need is java.io.* and the classes are File, FileReader, and BufferedReader.

The File class makes a virtual file within your program. The FileReader will read files from the disk into memory. And the BufferedReader will read those files in a streaming manner so you can read one line at a time.

I have the book Java for Dummies, which has a good example program using the file classes, but since publication apparently the standard syntax has changed so this article can serve as errata.

First we’ll need to import our libraries so make sure you use import java.io.*; at the top of your class.

Now we need to declare a File object called f. The syntax will be…

File f = new File(“test.txt”);

Here the file object we named f is being constructed as a new object of the File type from the File class and a parameter is being passed to the constructor which is the name of the virtual file we want to create. At this point the file only exists within our program. To make it a literal file on disk we can use the method within the File class called createNewFile to write the file to disk. Since we have our object the code would be something like f.CreateNewFile();

The problem with that though is there is no error checking so you have to do the statement within a try/catch block like this…

try{

f.createNewFile(); }

catch (IOException e){}

And we can put whatever error message within the last two braces we want which will be displayed if the file can’t be created for whatever reason. System.out.println(“Error making file.”); would work just fine.

Now to read a file we need to declare a variable which we’ll called fr from the FileReader type and initiate it with the value of null. The syntax would be…

FileReader fr = null;

That’ll do her. We needed a null because we need to put the assignment statement within a try/catch block so there is a possibility it would have no value if the attempt to assign it a value was not successful.

Now we want to write that try/catch block, but let’s look at what we are trying to do first. The syntax would be like… fr = new FileReader(f);

See? We could have written FileReader fr = new FileReader(f) which would have been a single statement, but Java won’t allow this because it could throw an exception so we have to break this into steps. First we declare a FileReader variable and give it the value of null, then we create a try/catch block and use it to try to give the FileReader variable a value by passing the virtual file we created already to it. The type of exception it could throw is a FileNotFoundException e. And we can use a e.printStackTrace(); as a simple way of handling the exception. A lot to remember, but you’ll see the whole code in a bit. Let’s move on to the last concept.

We need help from the BufferedReader to read a file efficiently so we declare a variable we’ll call in, since it’ll be used to get input from the file into our program and it will be of the BufferedReader type and we’ll pass our FileReader variable to the constructor as a parameter. The syntax will look like…

BufferedReader in = new BufferedReader(fr);

So let’s put it all together and we’ll recap.

import java.io.*;

public class Concordance {

public static void main(String[] args) {

File f = new File(“test.txt”);
try{
f.createNewFile();}
catch (IOException e){
System.out.println(“Couldn’t make the file”);
}

FileReader fr = null;

try {
fr = new FileReader(f);
} catch (FileNotFoundException e) {

e.printStackTrace();
}

BufferedReader in = new BufferedReader(fr);

}

There you have it. What does it all mean? Well we have our necessary import. Then we declare a File variable called F which makes a virtual file in our program called test.txt. The file directory wise resides in the residential directory of our java program, but we could get specific with the directory if we wanted to, but test.txt is fine.” We then try to create the file on the disk for realz yo. But we have to do this in a try/catch block.

Then we declare a variable called fr from the FileReader type and assign a value to it of null.

Then we try to give it a real value by passing our File variable which is called f to a FileReader constructor. It has to be in a try/catch block. If it fails we just see a print of the stack. No big deal.

Lastly we declare a variable called in which is of hte BufferedReader type. Luckily this one doesn’t throw exceptions so we don’t need a try/catch block, but we pass the variable fr which is a FileReader to it for the construction. Now we have an object called in which can do a lot of cool things.

This multiple step process of making one thing and passing into the construct of another is called wrapping. The File f is made, then a FileReader called fr wraps around it, then we wrap fr with a BufferedReader called in. Crazy huh?

Okay so how do we actually read a file’s contents into the memory of our program? Easy…

Once we’ve done our wrapping the variable in because an object that has all the BufferedReader methods included in it and so we can use those to read one line of the file at a time and show them.

First we define a String we could call lines using syntax like String lines = in.readLine();

Then we use a while loop which will read the file as long as what is being read is not null, in other words until it reaches the end of the file, and we show what it has read and then we grab the next line and loop. We need stupid try/catch statements and null initializations because of that and we need error handling so the syntax put together would look like this…

String lines = null;
try {
lines = in.readLine();
} catch (IOException e) {

e.printStackTrace();
}
while (lines != null){
System.out.println(lines);
try {
lines = in.readLine();
} catch (IOException e) {

e.printStackTrace();
}
}
try {
in.close();
} catch (IOException e) {

e.printStackTrace();
}

And that’s pretty much it. But it’s good practice to close the stream after you are done with it using the syntax in.close which calls the close method within the BufferedReader class, so I included that too. The problem is our program would create a blank file so it wouldn’t be reading anything right? So we either need to write some text into the file or we need to read a different file. For now just comment out the lines that say…

try{
f.createNewFile();}
catch (IOException e){
System.out.println(“Couldn’t make the file”);
}

so that they look like…

//try{
//f.createNewFile();}
//catch (IOException e){
//    System.out.println(“Couldn’t make the file”);
//}

And make sure you make a file in your java project directory called test.txt with a regular text editor which contains the text you want to read. And there you go.

The full program would look like…
import java.io.*;

public class Test {

public static void main(String[] args) {

File f = new File(“test.txt”);

//try{//creates a file, comment out if not necessary
//f.createNewFile();}
//catch (IOException e){
//    System.out.println(“Couldn’t make the file”);
//}

FileReader fr = null;

try {
fr = new FileReader(f);
} catch (FileNotFoundException e) {

e.printStackTrace();
}

BufferedReader in = new BufferedReader(fr);

String lines = null;
try {
lines = in.readLine();
} catch (IOException e) {

e.printStackTrace();
}
while (lines != null){
System.out.println(lines);
try {
lines = in.readLine();
} catch (IOException e) {

e.printStackTrace();
}
}
try {
in.close();
} catch (IOException e) {

e.printStackTrace();
}

}}

Now it doesn’t take a genius to figure out you could read these lines into an array instead of just displaying them.

Arrays themselves in Java are a bit strange. Different than in C. The typical syntax for a declaration of say an array of integers would be…

int[] myarray;

The array is of an indefinite size however so we set aside memory space for ten integers within our array like…

myarray = new int[10]

Or we could do it in one line like…

int[] myarray = new int[10];

String arrays are the same…

String[] my sa = new int [12];

or whatever.

Just remember the numbering system begins at zero, not one, as we access the array’s elements by those numbers so…

int[] myarray = new int[10];

myarray[0] = 114;

myarray[1] = 11;

System.out.println(myarray[0] + myarray[1]);

is fine.

Now one of the useful things about arrays is the indexing. We can pass through the variable list the array makes, the elements, one at a time because they are indexed with a number. Something like “show me the array’s element 1, then element 2, until we are all done” would be the idea.

This also works in reverse. Instead of reading elements from the array we can store information into the array in like manner. Something like “take the first number and store it in the first space of the array, the second one in the second space and so on until we are done.”

We’ll need a variable that will act as an number for the incremental access to one element after another and we’ll need a way to increase that number every time we do something. Looping will work. So what’s our variable?

int i = 0;

That’ll work. The variable label i is pretty traditional for indexing or incrementing.

Then we’ll need a way to increment. Normally…

i = i++;

Would works because it means to increase i by one, but we are starting at the number zero and 0+0 doesn’t work. So we have to be more specific and use…

i=i+1;

That should do her.

We’ll need an array to store the information from our “lines” variable, which means we’ll need a String array so…

String[] sa = new String[10];

Then we’ll need to assign the value from our “lines” to that array so…

sa[i] = lines;

Put it together and what have you got? Magic…
import java.io.*;

public class Test {

public static void main(String[] args) {
String lines = null;

//declares our file
File f = new File(“test.txt”);

//try{//creates a file, comment out if not necessary
//f.createNewFile();}
//catch (IOException e){
//    System.out.println(“Couldn’t make the file”);
//}

String[] sa = new String[10];
int i = 0;

//declares filereader
FileReader fr = null;

//wraps our file with our filereader
try {
fr = new FileReader(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}

///declares our bufferedreader
BufferedReader in = new BufferedReader(fr);

//wraps our filereader with bufferedreader
try {
lines = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}

//does a loop to read the file one line at a time
while (lines != null){

//System.out.println(lines);//shows what we are reading, not necessary so commented out

sa[i] = lines;//takes a line which we read and puts it into our array at
//variable number which we’ll increment

//tries to read another line into the lines variable
try {
lines = in.readLine();
}

catch (IOException e) {
e.printStackTrace();
}

//increments the element we are assigning a value to in our array
i = i+1;

}

//closes the file
try {
in.close();
}
catch (IOException e) {
e.printStackTrace();
}

//reads the array back to us
System.out.println(sa[0] + sa[1] + sa[3] + sa[4]  + sa[5]);
}}

Of course we could have made the code read it back to use incrementally in a loop or whatever, but you get the idea. The only problem with this program is that if our array isn’t big enough to hold the data within the file (because the file contains more than 10 lines) we’ll get an out of bounds error. We could pretty easily overcome this by writing the program to read the file first, checking how many lines it has and assigning that number to a variable which we could use to define our array in the first place. The program would jump around a bit, but that’s what methods are for. Keeps things nice and clean for us.

Now that we know how to read a file we should learn how to write one. We’ve already used the createNewFile method but the file was blank. Just as we did wrapping before to read a file we’ll want to wrap again to create a file that can be easily written to. The standard System.out.print or println method within Java we use for text output is part of the PrintWriter class so we need to connect it to a file using the FileWriter, BufferedWriter, and PrintWriter classes in a particular way. Normally all we need is the PrintWriter class.

The constructors and methods we may need for a program are…

PrintWriter(Writer out). That is the printwriter class where a Writer out is passed as a parameter which connects them wrapping the printwriter around the writer.

PrintWriter (Writer out, boolean flush) same but autoflushes if the second parameter is true (see below about flushing)

BufferedWriter (Writer out) creates a buffered writer and wraps it around the writer.

FileWriter (File file) Create a file writer from a file object. Throws IOException.

FileWriter (File file, boolean append) same, but sets whether each write appends to the end of the file.

FileWriter (String path) obvious

FileWriter (String path, boolean append) obvious

void close() which closes the file

void flush () which writes the contents of the buffer to disk.

int read() reads a single character file the file returning an integer and returning negative one if the end of the file has been reached. It throws an IOException so be aware.

void print (value) writes the value passed to it.

void println (value) same but inserts a line-break after.

The a program would look something like…
import java.io.*;

public class Test {

public static void main(String[] args) {
File myoutputfile = new File(“outputfile.txt”);
try {
myoutputfile.createNewFile();
System.out.println(“The file was created at this path “);
System.out.println(myoutputfile.getAbsolutePath());
} catch (IOException e1) {
e1.printStackTrace();
}
FileWriter myfilewriter = null;

//creates a filewriter and wraps it around the file
try {
myfilewriter = new FileWriter (myoutputfile,true);//omit comma true…
//…if you want to overwrite the contents of the file rather than append…
//…to the end of the file
} catch (IOException e) {
e.printStackTrace();
}

//createes a bufferedwriter and wraps that around the filewriter
BufferedWriter mybufferedwriter = new BufferedWriter(myfilewriter);

//creates a printwriter and wraps that around the bufferedwriter
PrintWriter myoutput = new PrintWriter(mybufferedwriter);

//writes to the file
myoutput.println(“hellos there! Hows r u?”);

//closes the file
myoutput.close();
}
}

Once again, magic.

Now our complete program to write files with proper methods to keep everything clean looks like this…

import java.io.*;

public class Test {

public static void main(String[] args) {
File f = makeFile(“test.txt”);

FileWriter fw = makeFileWriter(f, false);//use true if you want to append
BufferedWriter bw = makeBufferedWriter(fw);
PrintWriter pw = makePrintWriter(bw);
pw.println(“Hello Fellas”);
pw.close();
}

/////////
public static File makeFile(String s){
File f = new File(s);
try {
    f.createNewFile();
    System.out.println(“The file was created at this path: “);
    System.out.println(f.getAbsolutePath());
    }
    catch (IOException e1) {
    e1.printStackTrace();
    System.out.println(“the File was NOT successfully made”);
    }
return f;
}

//////////
public static FileWriter makeFileWriter(File f,boolean b){
FileWriter myfilewriter = null;

try{
myfilewriter = new FileWriter (f,b);//omit comma true…
System.out.println(“the FileWriter was successfully made”);
}
catch(IOException e){
System.out.println(“the FileWriter was NOT successfully made”);
}
return myfilewriter;
}

///////
public static BufferedWriter makeBufferedWriter(FileWriter fw){
BufferedWriter bw = new BufferedWriter(fw);
System.out.println(“BufferedWriter successfully made”);
return bw;
}

///////////
public static PrintWriter makePrintWriter(BufferedWriter bw){
PrintWriter pw = new PrintWriter(bw);
System.out.println(“PrintWriter successfully made”);
return pw;
}

}//end file

Now we’ll look at a program that reads from and writes to two different files. It’s all broken up into clean methods. Remember though for this to work the file being read must have at least three lines or you’ll get an out of bounds error.

import java.io.*;

public class Test {

public static void main(String[] args) {

//declare files
File filetoread = makeFile(“fileforinput.txt”);
File f = makeFile(“fileforoutput.txt”);

//wrap input file
FileReader fr = makeFileReader(filetoread);
BufferedReader br = makeBufferedReader(fr);

/// read and output a few lines from the bufferedreader
System.out.println(readALine(br));
System.out.println(readALine(br));
System.out.println(readALine(br));

//wrap output file
FileWriter fw = makeFileWriter(f, false);//use true if you want to append
BufferedWriter bw = makeBufferedWriter(fw);
PrintWriter pw = makePrintWriter(bw);

//output a couple of lines to the output file
pw.println(“Hello Fellas”);
pw.println(“How are you?”);
pw.println(“It’s a good morning isn’t it?”);

//close output file
pw.close();
}

private static String readALine(BufferedReader br){
    String s = null;
    try {
    s = br.readLine();
    }
    catch(IOException e){
        System.out.println(“Could not read a line from the file”);
    }
    return s;
}

private static FileReader makeFileReader(File f) {
    FileReader fr = null;

    try {
    fr = new FileReader(f);
    System.out.println(“FileReader was successfully made”);
    }
    catch (FileNotFoundException e) {
    e.printStackTrace();
    System.out.println(“FileReader could NOT be made.”);
    }
    return fr;
}
private static BufferedReader makeBufferedReader(FileReader fr){
    BufferedReader br = new BufferedReader(fr);
    System.out.println(“BufferedReader successfully made”);
    return br;
}

/////////
public static File makeFile(String s){
File f = new File(s);
try {
    f.createNewFile();
    System.out.println(“The file was created at this path: “);
    System.out.println(f.getAbsolutePath());
    }
    catch (IOException e1) {
    e1.printStackTrace();
    System.out.println(“the File was NOT successfully made”);
    }
return f;
}

//////////
public static FileWriter makeFileWriter(File f,boolean b){
FileWriter myfilewriter = null;

try{
myfilewriter = new FileWriter (f,b);//omit comma true…
System.out.println(“the FileWriter was successfully made”);
}
catch(IOException e){
System.out.println(“the FileWriter was NOT successfully made”);
}
return myfilewriter;
}

///////
public static BufferedWriter makeBufferedWriter(FileWriter fw){
BufferedWriter bw = new BufferedWriter(fw);
System.out.println(“BufferedWriter successfully made”);
return bw;
}

///////////
public static PrintWriter makePrintWriter(BufferedWriter bw){
PrintWriter pw = new PrintWriter(bw);
System.out.println(“PrintWriter successfully made”);
return pw;
}

}//end java program

Now a few other methods within the BufferedReader class that will come in handy include mark and reset. They both throw exceptions so you’ll have to put them in try/catch statements. The syntax for accessing mark would be in our case…

br.mark(1); //which sets a bookmark in the buffered reader at the beginning of very next character, which could be the very beginning of the file. Once that is done we can reset the reader to that point with…

br.reset

Remember your try/catch statements, but that should work for you.