Broad Network


Accessing File Basics in Java

Java Basics - Part 18

Forward: In this part of the series, I give you the basics on how to access files in Java.

By: Chrysanthus Date Published: 2 Sep 2012

Introduction

This is part 18 of my series, Java Basics. In this part of the series, I give you the basics on how to access files in Java. I assume you have read the previous parts of the series before reaching here, because the knowledge here is based on knowledge gained from the previous parts. We shall consider only text files and those, which are in the working directory (so we shall not bother about directory path). This means that your test code should remain in the working directory (java).

Note: If you cannot see the code or if you think anything is missing (broken link, image absent), just contact me at forchatrans@yahoo.com. That is, contact me for the slightest problem you have about what you are reading.

File Classes and Streams
In order for you to use a file in the hard disk or some other drive, you have to do what is called opening the file. For this, the content of the file is copied into memory. This area in memory that has the content of the file is called a stream. Whatever you want to do to the file (modifying the file, adding text to the end of the file, or just reading the file) you do to the stream. After that you have to do what is called closing the file. When a file is closed, the content of the stream is copied to the file in the disk, if necessary. Any modification of stream content or adding of text to the end of the stream is reflected in the file in the disk after closing. To be sure that the content of the file is saved to the disk, you can also do what is called flushing the file, but I will not address that in this tutorial.

A file may not exist in the disk. This means you have to create it. For this purpose, you still have to use the opening process (see below). A stream for the newly (not existing) opened file is created. You send information to the stream. When you close the file, effectively closing the stream, the content of the stream is copied to the disk for the first time. Closing a file means putting an end to the association between the stream and the corresponding file in the disk, after the content of the stream has just been copied to the file, which might or might not have existed, in the disk.

Note: the content of the stream is the file content copied from disk, if the file existed in the disk before it was opened.

In order to access files in the disk, you have to use some classes not written by you. These classes come with the Java compiler. These classes are in what is called the “java.io.*” package. You will not see the code of these classes. However you have to bring the code to memory (from disk) in order to use them in your program. So, your first line in your program would be:

    import java.io.*;

This statement brings the classes from the disk to memory (note the use of the reserved word, import). The names of the classes and their methods are known. I give you some below. You use the names and methods to access files in the disk.

Writing a File to Disk
One of the classes of the “java.io.*” package is called, PrintWriter. In the instantiation of its object, it takes a file name as argument. If the file does not exist, it is created. Any content that might have been in the file is overwritten (erased and new content written). The following program uses the PrintWriter to write a new file to disk.

import java.io.*;

class WriteNew
    {
        public static void main(String[] args) throws IOException
            {

                PrintWriter PW = null;

                try
                    {
                        PW = new PrintWriter("output.txt");

                        PW.println("This is the first line.");
                        PW.println("This is the second line.");
                        PW.println("This is the third line.");
                    }
                finally
                    {
                        PW.close();
                    }
            }
    }

This code has the, main class, the main method and a try block inside the main method. The code of interest is inside the try block. Instead of the catch block it has the finally block; just accept this, you will get the explanation later.

The program begins with an import statement of the “java.io.*” package, which brings up all the classes of the package to the memory. The main method throws an IOException object. IOException is a subclass of Exception. If you do not throw the exception in the try-block you can through it at the beginning of the method that has the try-block. I will give you the details of all these later. There is no catch block; I will also give you the detail explanation for that later.

The first line just before the try-block declares the PrintWriter object assigning the value of null to it. Here, null, which is a special constant variable, means nothing, and should be assigned to the object; I will explain why later.

The first line in the try-block actually instantiates the PrintWriter object. It takes as argument to the constructor method, the name of the text file that either already exist or is to be created. If the file already exists, any content it has is automatically erased for new content to be written, at this constructor level. It is the failure of this instantiation process that will throw the exception (indirectly). This particular instantiation process is also seen as the opening of the file. The detail explanation of some of the things said here will be given later.

Do not confuse between declaring an object and instantiating the object. Declaring simply says an object of a particular type (class) will exist. Instantiation is the actual creation of the object with a constructor. The declaration and instantiation phases can be combined in one statement.

The PrintWriter class has a method called, println(), meaning “print line”. It prints text to the output file (stream), line by line, one line for each call. At the end of any line printed, it prints the newline character unseen to you. It is the newline character that causes the next line to be printed below it.

Any file opened, has to be closed (see details later). The finally block here, has just one statement that closes opened file, using the variable of the PrintWriter object and the method of the PrintWriter object called, close().

Scoping
In Java, any variable declared inside a block cannot be seen inside another block out of the block. However, a variable declared outside a block above it, can be seen inside the block. The reason why the PW variable has been declared outside the try and finally blocks, is so that it can be seen both in the try and especially in the finally block. If it had been declared inside the try block, it would not be seen inside the finally block.

Read the above program again and try it; if the “output.txt” file does not exist in your working directory, it will be created.

Reading from a File
One of the classes in the “java.io.*” package is called, BufferedReader. This class has a method called, readLine(). This method reads the content of a text file, line-by-line. The method determines a line by detecting the newline character at the end of each line. In you code, you have to assign the line read to a string variable. Remember, the assignment operator is an operator. If its operation fails, it results in null. So, if while the text lines are being read and the end of the file is reached, the assignment operation results in null. If the file were empty, the assignment operation will still result in null. So the null situation can always be tested to see if the end of the file has reached or if the file is empty.

The instantiation of the BufferedReader object is the opening of the file whose content is to be read. It takes as argument the instantiation of an object from another class called, FileReader of the “java.io.*” package. The argument of the FileReader constructor is the actual name of the file whose content is to be read. If this process fails, an exception is thrown. Read and try the following code that reads the content of the file created above, line-by-line and display the result to the console:

import java.io.*;

class Reading
    {
        public static void main(String[] args) throws IOException
            {

                BufferedReader BR = null;

                try
                    {
                        BR = new BufferedReader(new FileReader("output.txt"));

                        String str;
                        str = BR.readLine();
                        System.out.println(str);
                        str = BR.readLine();
                        System.out.println(str);
                        str = BR.readLine();
                        System.out.println(str);
                    }
                finally
                    {
                        BR.close();
                    }
            }
    }

The structure of the program is the same as that of the previous one. So, I will just explain what is in the try and finally blocks. The first line in the try block instantiates an object of the BufferedReader type and assigns the returned value to the variable, BR. The argument of the BufferedReader constructor is the instantiation of an object of FileReader. The return object (value) here is not assigned to any variable; it is used directly as argument to the BufferedReader constructor. The FileReader constructor takes the file name whose content is to be read as argument. So, this first line opens the file.

Next in the try-block, you have the declaration of a string, str. This object (variable) will hold the next line read from the file (in memory). The next line in the code reads the first line from the file and assigns the text to the variable, str. After reading a line the BufferedReader object points to the next line on the file. In the code before the next line is read, the value of str is displayed to the command prompt window. Each time a line is read, the text value is assigned to the variable, str, replacing what was in str, before. We know that there are three text lines in the file, so there are three readLine() methods in the try-block.

Every file that is opened has to be closed. The statement in the finally block closes the file.

What about the case when you do not know the number of lines in the file? In this case, you will have to read each line and assign the text read to a string variable. If the assignment operation returns null, then it would mean that the end of the file is reached, and reading should stop. Read and try the following code that illustrates this:

import java.io.*;

class ReadingWhile
    {
        public static void main(String[] args) throws IOException
            {

                BufferedReader BR = null;

                try
                    {
                        BR = new BufferedReader(new FileReader("output.txt"));

                        String str;
                        while ((str = BR.readLine()) != null)
                            {
                                System.out.println(str);
                            }
                    }
                finally
                    {
                        BR.close();
                    }
            }
    }

In this program, the line is actually read in the while condition. The text read is assigned to the variable, str. The block of the while loop has just one statement that prints the text to the console (command prompt). Remember: after reading, the BufferedReader class points to the next line. When the end-of-file is reached, the assignment operator in the while condition results in null and the block of the while loop is not executed any more. In the while condition, the result of the assignment operator is always compared to null, with the not-equal-to operator (i.e. “!=”). Note the use of parentheses in the while condition. The pair just after readLine is for the readLine method.

Simple Editing of Text File
A simple way to edit a file, is to read all the content of the file, modify it and then replace all the file content with the modified content. You can read all the content of the file into an array, where each line from the file goes into a cell in the array. You can also read all the content into one string variable.

The following program reads the lines of the file above and copies the lines into an array, each line to an array cell; the content of all the array cells concerned are modified and everything re-written back to the file, replacing the previous content of the file:

import java.io.*;

class ReadEditArray
    {
        public static void main(String[] args) throws IOException
            {

                BufferedReader BR = null;
                PrintWriter PW = null;

                try
                    {

                        BR = new BufferedReader(new FileReader("output.txt"));

                        String[] linesArr = new String[100];
                        int arrayCounter = 0;
                        while ((linesArr[arrayCounter] = BR.readLine()) != null)
                            {
                                ++arrayCounter;
                            }

                        //change all the array elements
                        linesArr[0] = "This is line A.";
                        linesArr[1] = "This is line B.";
                        linesArr[2] = "This is line C.";

                        PW = new PrintWriter("output.txt");
                        for (int i=0; i<arrayCounter;++i)
                            {
                                PW.println(linesArr[i]);
                            }

                    }
                finally
                    {
                        BR.close();
                        PW.close();
                    }
            }
    }

When you define an array in Java, you have to quote the size. Since you usually will not know the number of lines in the file, you have to quote a size for that array that is the possible maximum number of lines. So, I chose 100 for the size of the array. The integer variable, arrayCounter, is to count the number of lines in the file; this is the number of cells in the array that ultimately have line strings. In the while loop, the counter is incremented after each line read.

Note the position of the PrintWriter object instantiation in the code. The PrintWriter class has the property that when an object is instantiated from it, it deletes all the content of the physical file. So, in the code, the PrintWriter object instantiation statement is placed after the file lines have been read into the array. The rest of the code should be self-explanatory. Read through the code and try it.

What about the case where all the file content is read into one string? In the following example, all the file content is read into one string; the content of the string is then replaced (modified), after which, the new version is sent to replace the previous file content.

import java.io.*;

class ReadEditStr
    {
        public static void main(String[] args) throws IOException
            {

                BufferedReader BR = null;
                PrintWriter PW = null;

                try
                    {

                        BR = new BufferedReader(new FileReader("output.txt"));

                        String totalString = "";
                        String tempString; //for storing line temporary
                        while ((tempString = BR.readLine()) != null)
                            {
                                totalString = totalString + tempString;
                            }

                        //replace content of totalString
                        totalString = "aaa AAA 111\r\nbbb BBB 222\r\nccc CCC 333\r\n";

                        PW = new PrintWriter("output.txt");
                        PW.print(totalString);
                    }
                finally
                    {
                        BR.close();
                        PW.close();
                    }
            }
    }

Here there are two strings with the following declaration:

                        String totalString = "";
                        String tempString; //for storing line temporary

The first one, totalString initialized to, “”, which means, string with no text, will acquire all the lines read, attached next to one another. The second one, tempString will hold one line at a time, read from the file. In the while loop block, the lines are attached to the totalString as follows:

                                totalString = totalString + tempString;

A while loop executes its block over and over. Each time this statement is executed, the content of the new string, tempString just read, is added to the end of the old string, totalString, and the assignment operator here, replaces the content of the old string with that of the newly combined string. That is what the statement does, read from its right hand side. In that way, all the lines of text in the file, accumulates (from top to bottom), into one long string. The while loop collects all the lines of text from the file into the string, totalString.

Below in the code, all the content of totalString is replaced as follows:

        totalString = "aaa AAA 111\r\nbbb BBB 222\r\nccc CCC 333\r\n";

In the string literal here, there are actually three lines, each ending with the carriage return and newline character, “\r\n”, all the lines in one string at the moment. The rest of the code is self-explanatory.

Note: When a file is opened from disk, its content is read into an area of memory called a stream. Above, the file has been opened with the BufferedReader stream. You can then read the lines of the file from the stream one by one into an array or into an accumulated string. When writing to a file, you write but to another stream in memory. In this case it is the PrintWriter stream. When the stream is closed, the content of the stream is saved to disk. A stream opened for reading, also has to be closed.

End of Tutorial
I hope now, you can read a text file, write to a text file and edit a text file, in Java. A text file normally consists of lines ending, with “\r\n”.

End of Series
We have come to the end of the series. I hope you appreciated it. If you have understood most of the principles of the series, then you should be able now to write simple or basic programs in Java. There is more to learn in Java to become a professional or an expert. Check out the link below titled, Java Course. Remember, Java comes with its own operating system. So in theory, you can learn Java as your only programming language, which will enable you to do so much in life. I hope you continue learning Java from the link directing you, below.

Chrys

Related Articles

Java Course

Comments

Become the Writer's Fan
Send the Writer a Message