File Processing

Random Access Text File Processing a Random Access File Practice
Summary Exercise

Learning Outcomes

On completion of this section you will be familiar with:

Download pdf version

Introduction

All of our data up to now was fairly nebulous in that it existed only while our programmes were running. Once those programmes stopped running the memory allocated to them and their data was wiped clean and thus the data was irretrievably lost. Up to now it did not matter as the amount of data was so small and we simply concentrated on the processing of that data and not on storing large amounts of it.

In a real life situation if we were processing a payroll we would need to keep permanent records of the results since we would need to supply yearly statements both to the inland revenue and to the individual employees. The way of doing this is to store data in a disk file. In this chapter we shall be looking at one of the simplest forms of data storage – a random access text file

A Random Access Text File

Go to top

If we were to store the following data in a text file: hours worked, hourly rate and superannuation code, then the first thing we need to do is decide on what data types we are going to use for each item. If we decide on the type double for the hours and rate and the type int for the superannuation code, then, since the type double is 8 bytes long and the type int is 4 bytes long. Thus for each employee we would use 8 + 8 + 4 = 20 bytes to store the data on a disk file.  The structure would look as follows:

hours

rate

Super code

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The example above shows a file structure which has three fields or columns as they are called in some texts.  The first field, named hours is 8 bytes long, the second field, rate, is also 8 bytes long while the last field super code is 4 bytes long.

If we begin with the above structure then we need to abide by it through our application. The reason is that since the length of each record is 20 bytes then we can tell the system to go to any record in the file directly rather than having to search from the beginning of the file. In most file systems positioning of the bytes starts at zero and thus in the above structure we are looking at bytes 0 – 19.  The records themselves start counting at 0 as well.  Thus if we wanted the fifth record we would simply multiply 4 by 20 and thus we would know to go directly to bytes position 80 to pick up the beginning of the fifth record. Since we know that that record, like all of the other records are structured as 8, 8, 4, then once we got to position 80 we would read 8 bytes, followed by another 8 bytes and finally read 4 bytes.  This would incidentally position us at the beginning of the sixth record.  Since a file generally has more than one record the illustration below is more descriptive of a real file than that above.

hours

rate

Super code

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Processing a Random Access File

Go to top

Let us now look at an application that uses a file structure similar to the above to store data a bout a series of payroll data.

To begin with we have an updated version of our keyboard reader. In this case we have created a class, an object of which can read the keyboard data and has three methods for returning the data as String, double or int.

Listing 13.1

 1

import java.io.IOException;

 2

public class ReadKeyboard

 3

{

 4

  byte[] input;

 5

  boolean dataRead;

 6

  public ReadKeyboard(){};

 7

  String inputString;

 8

  public ReadKeyboard(String prompt)

 9

  {

 10

    input = new byte[20];

 11

    try

 12

    {

 13

      System.out.println(prompt);

 14

      System.in.read(input);

 15

      inputString = new String(input);

 16

      dataRead=true;

 17

    }

 18

    catch(IOException e)

 19

    {

 20

      dataRead=false;

 21

    }

 22

  }

 23

  public String stringValue()

 24

  {

 25

    return inputString;

 26

  }

 27

  public int intValue()

 28

  {

 29

    try

 30

    {

 31

      return Integer.parseInt(inputString.trim());

 32

    }

 33

    catch(NumberFormatException n)

 34

    {

 35

      return Integer.MIN_VALUE;

 36

    }

 37

  }

 38

  public double doubleValue()

 39

  {

 40

    try

 41

    {

 42

      return Double.parseDouble(inputString.trim());

 43

    }

 44

    catch(NumberFormatException n)

 45

    {

 46

      return Double.NaN;

 47

    }

 48

  }

 49

}

 

The constructor of this class, which spans lines 8 – 22, accepts the user’s prompt. It has its own byte array at line 10 into which it accepts the keyboard input. In a try block at lines 11 – 17 it displays the prompt, reads the keyboard and converts the data to a String which is stored in the class variable inputString. Finally it sets the flag dataRead to true. If an exception has been thrown then at line 20 the flag is set to false.

The method stringValue simply returns the value of inputString directly. 

The method intValue returns the integer value of the same String, and in case an exception is thrown it sends the MIN_VALUE of the Integer class.

The doubleValue method works in a similar manner for that data type.

Finally let us look at the class for processing an actual file in Listing 13.2 below.

Listing 13.2

 1

import java.io.FileInputStream;

 2

import java.io.FileOutputStream;

 3

import java.io.IOException;

 4

import java.io.FileNotFoundException;

 5

import java.io.DataInputStream;

 6

import java.io.DataOutputStream;

 7

public class FileProcessing

 8

{

 9

  public void writeToFile(String fileName)

 10

  {

 11

    try

 12

    {

 13

      double value;

 14

      int value1;

 15

      FileOutputStream fo = new FileOutputStream(fileName);

 16

      DataOutputStream dos = new DataOutputStream(fo);

 17

      value = new ReadKeyboard("Enter Hours").doubleValue();

 18

      while(!Double.isNaN(value))

 19

      {

 20

        dos.writeDouble(value);

 21

        value = new ReadKeyboard("Enter Rate").doubleValue();

 22

        dos.writeDouble(value);

 23

        value1 = new ReadKeyboard("Enter Super code").intValue();

 24

        dos.writeInt(value1);

 25

        value = new ReadKeyboard("Enter Hours").doubleValue();

 26

      }

 27

      dos.close();

 28

      fo.close();

 29

    }

 30

    catch(FileNotFoundException fnf){}

 31

    catch(IOException ioe){}

 32

  }

 33

  public void readFromFile(String fileName)

 34

  {

 35

    Pay p;

 36

    double hours, rate;

 37

    int superCode;

 38

    try

 39

    {

 40

      FileInputStream fis = new FileInputStream(fileName);

 41

      DataInputStream dis = new DataInputStream(fis);

 42

      while(dis.available()>0)

 43

      {

 44

        hours = dis.readDouble();

 45

        rate = dis.readDouble();

 46

        superCode = dis.readInt();

 47

        p = new Pay(hours,rate,superCode);

 48

        p.calculate();

 49

        System.out.println(p.toString());

 50

      }

 51

      dis.close();

 52

      fis.close();

 53

    }

 54

    catch(FileNotFoundException fnf)

 55

    {}

 56

    catch(IOException io){}

 57

  }

 58

}

 

The class simply consists of two methods writeToFile and readFromFile. In the first method, which spans lines 9 – 32, most of the processing takes place inside a try block. At lines 13 and 14 we declare two variables that we shall use to store the keyboard data before storing it in the file.

At line 15 we create an object of the class FileOutputStream and pass to its constructor the name of the file that we are to write data to.  FileOutputStream can be regarded as a road or channel that has been opened between the computer’s memory and the disk on which the data is to be stored. It does not, in our case, deal with any data types or structures. Instead it simply looks after the data transfer protocols between the memory and the file. In order to take care of the actual data itself we create an object of the class DataOutputStream at line 16. We pass to this object’s constructor a pointer to the FileOutputStream object we created earlier. This last object we created will take care of the data structures.

Next we commence reading the data from the keyboard. The sequence we shall read it is hours, rate and super code. A while loop will be used to control the keyboard entry. Once a blank is received from the keyboard the loop will terminate.  The first two double values received from the keyboard are written to the file at lines 20 and 22. The method writeDouble simply writes 4 bytes of data to the file, which are encoded as the type double. Similarly, at line 24, writeInt writes an integer value to the file.  Thus by line 24 two doubles and an int are written to the file. On the next iteration of the loop a similar sequence will be written until the user eventually terminates the loop. Once this occurs the two streams are closed at lines 27 and 28.

The method readFromFile spans lines 33 – 58. The method’s variables consist of a pointer to the class Pay, and the variables hours, rate and superCode.  Again all of the processing takes place inside a try block.  The classes FileInputStream and DataInputStream are very similar to their equivalents above except that they are involved with data going from a disk file to the memory. Thus their methods are read methods instead of write methods.

A method that belongs to the class DataInputStream is the method available. This method needs a little explanation.  When we open a text file for reading a file pointer is positioned at the start of the file and as we read data from that file the pointer moves along with us. The method available simply counts the number of bytes between the current position of the file pointer and the end of the file. We use this method in our application to prevent us from trying to read beyond the end of the file. Thus at line 41 once the DataInputStream object is created the file pointer is positioned at the start of the file. Unless its an empty file the condition at line 42 will be false and thus at lines 44 – 46 two double and one int values re read from the file. (This of course will cause the pointer to move along by 20 bytes towards the end of the file. Once the three values are read an object of the class Pay is created and the three values that have been read are passed to its constructor. Its calculate method is called at line 48 and the result of the calculation is displayed at line 49. The loop iterates once more to read the next record where the same processing occurs.

Finally the code below starts off the application by first creating an object of FileProcessing and then calling its two methods.

Listing 13.3

 1

public class Untitled1

 2

{

 3

  public static void main(String[] args)

 4

  {

 5

    FileProcessing fp = new FileProcessing();

 6

    fp.writeToFile("Employees");

 7

    fp.readFromFile("Employees");

 8

  }

 9

}

 

Practice

Go to top

Copy the above code into your computer, then compile and run it. Once it is running satisfactorily, alter the processing so that once the hours and rate are received in the method writeToFile the gross, tax, superannuation and nett are calculate immediately and stored in the file along with the rest of the data.  Thus in the method readFromFile no processing occurs. It simply reads the data items from the file and prints the results.

Summary

Go to top

A text file is a structure which consists of records, which themselves are made up of fields. Each record is of a fixed size so that the position of each record can be easily calculated by the system for fast retrieval of data.

In Java we use a combination of objects of the classes FileOutputStream and DataOutputStream to write data to the file. The former establishes connection between the memory and the disk while the latter takes care of the data structure that is to be transferred.

To read data from a file we use combination of objects of the classes FileInputStream and DataInputStream.


Exercises

Go to top

Exercise 13.1

1.      What is a record?

2.      What is a field?

3.      Give alternative names for record and field.

4.      Explain the use of objects of the classes FileInputStream and DataInputStream.

5.      What are the similarities and differences between FileInputStream and FileOutputStream?

6.      Discuss the methods writeDouble and writeInt.  These are closely matched by two other methods. What are they?

 Exercise 13.2


Modify Exercise 12.1 so that when the user input is received the calculations for GST, price including GST and total charged to customer are stored in a file instead of being displayed on the screen. There must be a method in your class for reading the data from the file and displaying it. This method will not perform any calculations.
Use listings 13.1, 13.2 and 13.3 above as models or templates of how to create the new application.