At the end of the chapter, you will be able to understand and program
We have all heard about streams of water; we call them springs flowing from top of hills to plains. In Java, flow of data from output device to computer system and computer to any one of the output devices is called Stream or IO streams.
This chapter will introduce you to concepts of IOStreaming and stream classes like ByteStream and Character Stream classes. We will introduce you to the concept of Random File IO. This chapter also discusses in detail File IO and Errors and Exceptions that are encountered while dealing with file. The topics on file handling presented includes input and output of characters, Bytes, primitive data types and Data Streams, and object Streams.
In Java, IO streams are flow of bytes from one input device to Memory and vice versa. A stream is like a pipe. It can carry anything in the pipe, be it primitive data, objects, etc. Refer to Figure 21.1.
Figure 21.1 Streams – a concept
The diagram on the left-hand part shows a water tank with input pipe and an output pipe. The diagram on the right-hand part shows input stream from CD drive and output stream to monitor.
Figure 21.1 takes a closer look at IO. For example, Java source is required to be converted by JRE to suit Input devices such as computer system. Hence input from IO devices are buffered first, then picked up by the computer system. Similarly, output from computer is buffered first and then picked up by slow-speed devices like printer, memory, etc. Figure 21.2 provides a more detailed view of IO-streaming.
Figure 21.2 IO Streaming – a close look
As an example, consider the case of inputting from keyboard. To read the data from the keyboard, we need to attach InputStreamreader to accept the input data from keyboard and to place it on buffer we need BufferedReader.
DataInputStreamReader accepts the data from keyboard and System.in represents keyboard. Therefore, we can write
DataInputStremReader input = new DataInputStremReader(System.in);
Figure 21.3 shows IO StreamReader for input from keyboard. System has three fields representing three different devices. They are:
Figure 21.3 Input from keyboard
Before we go into details of IO Streaming, it is necessary to review files. We would come across files everywhere we go. For example, colleges keep a file for each of their students. Similarly municipality holds files containing details of taxes to be paid by citizens. Indeed files are so common in our lives; Java language and other languages support files. What is a file? A file is a collection of records.
Java.io package contains stream classes for handling File IO. Stream Files can be divided into two types: ByteStream classes and Text Files, also known as CharacterStream classes. These two streams are derived form Java's Object class, as shown in Figure 21.4. Table 21.1 gives details of classes. These Stream classes read from source and write to destination. The source and destinations are: Memory, pipe, and File. Pipes are used for handling threads in Java.
Table 21.1 Java stream classes
ByteStream Classes | CharacterStream Classes Text Files |
---|---|
FileInputStream | FileReader |
FileOutputStream | FileWriter |
BufferedInputStream | BufferedReader |
BufferedOutputStream | BufferedWriter |
The data is represented as byte ( 8 bits). All text files, and audio and video files that need to be transmitted using Internet, are stored using ByteStream Classes. Table 21.2 provides details of input stream and output stream classes. Table 21.3 provides details of member methods Java InputStream/OutputStream classes.
Table 21.2 Java ByteStream classes – classification
Table 21.3 Members of java inputstream/outputstream classes
InputStream Methods | OutputStream Methods |
---|---|
read() : Read a byte read( byte[ ] a) :Read an array b read( byte[ ] b , int n ,int s ) : Read an array b n bytes from s. |
write():write a byte write ( byte[ ] a) : write an array b write ( byte[ ] b , int n ,int s ) : write an array b n bytes from s. |
available() : Returns no of bytes | close( ) : closes output stream file |
skip(m) : Skips m bytes from input stream | flush( ) : flushes output stream file |
reset() : Goes to beg of file close() : Closes the stream file |
------------------ |
The data is represented by character, i.e., two bytes. They are best suited to handle all text files. The classification of CharacterStream classes are shown in Table 21.4.
Table 21.4 Java characterstream classes – classification
Reader | Writer |
---|---|
BufferedReader | BufferedWriter |
CharArrayReader | CharArrayWriter |
FilterReader : PushbackReader |
Filter Writer: PrintWriter |
InputStreamReader FileReader |
OutputStreamWriter FileWriter |
PipedReader | PipedWriter |
StringReader | StringWriter |
Note that DataInputStream is a very useful class for reading primitive data. It extends to FilterInputStream and implements DataInput. Accordingly it supports: readShort(), read Int(), readDouble(), readLong(), readLine(), readLong(), readFloat(), readChar(), readBoolean(), and a unified text format called readUTF(). Refer to Figure 21.5.
Figure 21.5 Input from keyboard output to a file using FileOutputStream
Note further that dataOutputStream is a class for outputting primitive data. It extends to implements DataOnput. Accordingly, it supports writeShort(), write Int(), writeDouble(), writeLong(), writeLine(), writeFloat(), writeChar(), writeBoolean(), and a unified text format called writeUTF().
DataInputStream of InputStream class and FileOutputStream of OutputStream class are shown in Figure 21.5. In this problem, the user can enter statements line by line. When he wants to stop, he can enter a dot to stop the program. Be advised and remember that FileInputStream and FileOutputStream handle byte bases (8 bits) data. FileReader and FileWriter handle 16 bit, i.e., character data type.
Example 21.1: CharByChar.Java A Program to Copy a File Character by Character. It Uses FileInputStream and FileOutputStream
Let us attempt a problem. We will read character by character and write on to a file called File1. Then we would copy the content of File1 to File2 character by character. Display the copied file File2.
1. package com.oops.chap21;
2. import java.io.*;
3. public class CharByChar {
4. public static void main(String[] args) throws IOException{
5. DataInputStream input = new DataInputStream(System.in);
6. FileOutputStream fos1 = new FileOutputStream(“File1.dat”);
7. FileOutputStream fos2 = new FileOutputStream(“File2.dat”);
8. System.out.println(“Enter text < enter . at end>”);
9. int ch;
10. while( (ch=(char)input.read())!=’.’){
11. fos1.write(ch); }
12. fos1.close();
13. // copy fos1 to fos2 character by character
14. FileInputStream fis = new FileInputStream(“File1.dat”);
15. System.out.println(“Copyinf from File1 & File2…..”);
16. while((ch=fis.read())!=-1)
17. fos2.write(ch);
18. fis.close();
19. fos2.close();
20. //Now open the fos2 i.e. FIle2.dat and display the result
21. fis=new FileInputStream(“File2.dat”);
22. System.out.println(“Displaying the details from File2…..”);
23. while((ch=fis.read())!=-1)
24. System.out.println((char)ch);
25. }// end of main
26. }// end of clss CharByChar
Output : Enter text < enter . at end>
I Love India!
I love World.
Copyinf details from File1 & File2…..
Displaying the details from File2…..
I Love India!
I love World
Line No. 5: | creates object of DataInputStream input and attaches the keyboard (System.in) |
Line Nos. 6 & 7: | FileOutputStream fos1/fos2 = new FileOutputStream (“File1/2.dat”); creates object for FileOutputStream and names the file as File1/2.dat. |
Line Nos. 8–11: | reads character from key board and write to file File1.dat. This process continues till user enters a dot(.) |
Line No. 12: | closes fos1. |
Line No. 14: | creates object called fis for reading from File1: FileInputStream fis = new FileInputStream(“File1.dat”); |
Line Nos. 16 & 17: | reads from object fis (i.e. File1.dat) and copies to fos2 (i.e. File2.dat). Line No. 23 and 24 display the File2 contents. |
In the example so far we have handled, we have used Byte-based IO, i.e., FileInputStream and FileOutputStream and they use 8 bits (1 byte). Our next example shows copying a file using character streams that use 16 bits (2 bytes), i.e., FileReader and FileWriter. Note that FileReader converts 8 bit character to 16 bit UTF character. The 16 bit character will be returned as int. So there will be no difference between the usage. Only the underlying representation of the character is different:
Example 21.2: FileReaderWriter.Java A Program to Copy a File Using Character Streams. Obtain the Input and Output File Names Interactively from Keyboard. Use Scanner Class
1. package com.oops.chap21;
2. import java.io.*;
3. import java.util.Scanner;
4. public class FileReaderWriter {
5. public static void main(String[] args) {
6. String filename1,filename2;
7. Scanner scn=new Scanner(System.in);
8. DataInputStream input = new DataInputStream(System.in);
9. System.out.println(“Enter output FileName :”);
10. filename1=scn.next();
11. System.out.println(“Enter FileName for copy file :”);
12. filename2=scn.next();
13. try{
14. FileWriter fw1 = new FileWriter(filename1);
15. FileWriter fw2 = new FileWriter(filename2);
16. System.out.println(“Enter text < enter . at end>”);
17. int ch;
18. while( (ch=(char)input.read())!=’.’){
19. fw1.write(ch);
20. }
21. fw1.close();
22. FileReader fr1 = new FileReader(filename1);
23. while((ch=fr1.read())!=-1)
24. fw2.write(ch);
25. fr1.close();
26. fw2.close();
27. //Now open filename3 and dispaly the result
28. fr1=new FileReader(filename2);
29. System.out.println(“Displaying the details from “+filename2);
30. while((ch=fr1.read())!=-1)
31. System.out.println((char)ch);
32. }catch(IOException e){}
33. }
34. }
Output : Enter output FileName :citynames
Enter FileName for copy file :citnamescopy
Enter text < enter . to end>
Hello India.
Displaying the details from citnamescopy
Hello India
Line No. 6: | defines filename1 and filename2 as String data type to accept the file names interactively from the user. |
Line No. 7: | defines a Scanner object scn to read the data from keyboard. |
Line No. 8: | defines DataInputStream object and attaches keyboard (System.in) |
Line Nos. 9–12: | Accept file names from the user. |
Line Nos. 14 & 15: | create objects fw1 & fw2 for FileWriter class. |
Line Nos. 16–21: | are statements for reading from keyboard and writing on to output file denoted by filename1. |
Line No. 21: | FileReader fr1 = new FileReader(filename1); creates an object fr1 for filenam1. Line Nos. 23–26 copies the content from filename1 to filename2. |
Line Nos. 28–31: | display the content of copied file filename2. |
Basic IO operations are likely to throw exceptions. All checked IO exceptions have to be handled by the user using try and catch blocks. If any exception is not being handled, then the user has to throw the exception like: public static void main(String [] args) throws IOException. The exceptions likely are listed in Table 21.5.
Table 21.5 IO Errors and exceptions
Input IO | Remarks |
---|---|
EOFException | End of file marker |
FileNotFoundException | File not found |
InterruptedIOException | IO interrupted |
IOException | General IO Exception |
Filter streams basically alter the output to suit a specified need. For example, it can be wrapped around DataInputStream or BufferedInputStream. The steps involved in using FilterStream are as follows:
The following examples make things clear:
1 DataInputStream input = new DataInputStream(System.in);
while( (ch=(char)input.read())!=’.’){
Note that DataInputstream has been derived from filterInput-stream
2. FileOutputStream fileout = new FileOutputStream(“DisDos”);
DataOutputStream dosfile= new DataOutputStream(fileout);
CPU is a fast device and memory is a slow device compared to CPU. Therefore, when we are trying to copy character on to file, the Operating System is called to coordinate the transfer from CPU to memory. This is slow and inefficient. Instead if we can provide a buffer, a temporary memory space, so that the system can write on to buffer and once buffer is filled, then OS writes to memory all at once. This is the Producer–Consumer problem we have discussed in Chapter 20.
Java provides this functionality through BufferedInputStream and BufferedOutputStream, thus enhancing the efficiency of IO operations. Example 21.4 deals with the method of writing data using BufferedOutputStream and reading data using BufferedInputStream. Figure 21.6a and 21.6b shows the concepts involved.
Figure 21.6a BufferedOutputStream
Figure 21.6b BufferedInputStream
FileInputStream, FileOutputStream, FileReader and FileWriter classes are provided by Java to cater to byte and character types. But what do we do in case we want input and output of basic primitive data types like int, char, float, etc. DataInputStream and DataOutputStreams wrap FileInput and FileOutputStreams and allow us to deal with basic data types. Figure 21.7 shows the concept involved for DataOutputStream:
Figure 21.7 DataOutputStream
Example 21.3: DisDos.Java A Program to Show Use of DataInputStream and DataOutputStream Using Scanner Class
1. package com.oops.chap21;
2. import java.util.*;
3. import java.io.*;
4. import javax.swing.JOptionPane;
5. public class DisDos {
6. public static void main(String[] args) throws IOException{
7. int idNo;
8. double credits,debits,netPay;
9. System.out.println(“Enter Emp idNo,credits,debits separated by spaces”);
10. Scanner scn = new Scanner(System.in);
11. idNo=scn.nextInt();
12. credits =scn.nextDouble();
13. debits=scn.nextDouble();
14. netPay=credits-debits;
15. FileOutputStream fileout = new FileOutputStream(“DisDos”);
16. DataOutputStream dosfile= new DataOutputStream(fileout);
17. dosfile.writeInt(idNo);
18. dosfile.writeDouble(credits);
19. dosfile.writeDouble(debits);
20. dosfile.writeDouble(netPay);
21. dosfile.close();
22. fileout.close();
23. //Now red data from DisDos file
24. FileInputStream filein = new FileInputStream(“DisDos”);
25. DataInputStream disfile= new DataInputStream(filein);
26. JOptionPane.showMessageDialog(null,” Id Number :” +disfile.readInt() +”
Credits :” +
27. disfile.readDouble()+” Debits “ + disfile.readDouble() +” Net Pay :”+
28. disfile.readDouble(),”Employee Pay Bill”,JOptionPane.PLAIN_MESSAGE);
29. }
30. }
Output: Enter Emp idNo,credits,debits separated by spaces
50595 25000.00 5000.00
Line Nos. 10–14: | capture input data from keyboard using scanner class. |
Line Nos. 15–16: | wrap around DataOutputStream object dosfile on to FileOutputStream object fileout created at Line No. 15. This is how FilterOutputStream works. |
Line Nos. 24–25: | similarly use DataInputStream wrapped around FileInputStream. |
Line Nos. 26–28: | use swing components to display output through message box. |
File class helps us in creating files and directories. It has all housekeeping methods related to files such as creating, opening, closing, deleting , getting name and size of the file, renaming the file, etc.
We have been using FileInputStream and FileOutputStream by throwing IOException. Program comes to a halt. But is there a better way to check if the file could be opened or not? File class and object of File can test if the file is actually allocated and other jobs such as listing of directories, etc. A file is created using a string file name and can then be tested to see different methods offered by File class. The methods offered by File class are shown in Table 21.6.
Method | Functionality |
---|---|
boolean isFile() | Returns true if it is a file |
boolean isDirectory() | Returns true if it is a directory |
boolean canRead() | Returns true if file object is readable |
boolean canWrite() | Returns true if file object is writable |
boolean exists() | Returns true if file/dir exists |
String getParent() | Returns parent directory |
String getPath() Strng getAbsolutePath() |
Returns path Returns absolute path from root dir |
long length() | Returns size of file in bytes |
boolean delete() | Deletes the file |
boolean createNewFile() | Creates a new file if file does not exist |
boolean mkdir() | Makes directory |
boolean rename(File filename) | Renames the file |
String[] list() | Returns a list of file and directories |
Example 21.4: FileDemo.Java A Program to Show Use Java's File Class
1. package com.oops.chap21;
2. import java.io.*;
3. public class FileDirectory {
4. public static void main(String[] args) throws IOException{
5. System.out.println(“ Getting File Details……”);
6. File fobj = new File(“/”,”Oopsjava/workspace/oopstech2/src/com/chap21/DisDos.java”);
7. System.out.println(“File Name :” + fobj.getName());
8. System.out.println(“File Absolute path :” + fobj.getAbsolutePath());
9. System.out.println(“Parent:” + fobj.getParent());
10. System.out.println(“File exists or not:” + fobj.exists());
11. if(fobj.isFile())System.out.println(“ Length “ + fobj.length());
12. System.out.println(“is directory?” + fobj.isDirectory());
13. System.out.println(“ Getting Directory Details……”);
14. File fobj2 = new File(“/”,”Oopsjava/workspace/oopstech2/src/com/chap21”);
15. if(fobj.exists())
16. { // get the listing of a directory into a array
17. String arrList[] = fobj2.list();
18. int len=arrList.length;
19. System.out.println(“Displying the Directory Listing……..”);
20. for ( int i=0; i<len;i++)
21. { System.out.println(arrList[i]);
22. File ftemp=new File(“/Oopsjava/workspace/oopstech2/src/com/chap21”,arrList[i]);
23. if ( ftemp.isFile())
24. System.out.println(“File :”+ ftemp.getName() + “length :” + ftemp.length());
25. else System.out.println(“**”);
26. }//end of for
27. }// end of if
28. }//end of main
29. }//end of class
Output: Getting File Details……
File Name :DisDos.java
File Absolute path :C:Oopsjavaworkspaceoopstech2srccomchap21 DisDos.java
Parent:Oopsjavaworkspaceoopstech2srccomchap21
File exists or not:true
Length 1127
is directory?false
Getting Directory Details……
Displying the Directory Listing……..
FOS.java
File :FOS.javalength :715
CharByChar.java
File :CharByChar.javalength :976
ByteByByte.java
File :ByteByByte.javalength :178
Line No. 6: | shows the creation of File object: Observe that we have to give full directory of file such as: File fobj = new File(“/”,”Oopsjava/workspace/oopstech2/src/com/chap21/DisDos.java”); |
Line Nos. 7–12: | show usage of several File class method such as isFile(), isDirectory() And getAbsolutePath(), and getparent(), etc. |
Line No. 10: | checks if specified file or directory exists by: fobj.exists() method. |
Line No. 17: | String arrList[] = fobj2.list(); gets the files and directories and allocates them to String arrList[] |
Line No. 21: | attaches arrList[i] with a File object and gets length and name at Line No. 24. |
In this mode of access, a record is accessed using index maintained for this purpose. It is like going to a chapter and within the chapter to a page of interest, using the Index provided at the end of the book. The file can be accessed from any location. It implements both DataInput and DataOutput interfaces and extends to Java's base class Object. The syntax for using random files in Java is
RandomAccessFile( File obj , String Access Specifier);
RandomAccessFile( String filename , String Access Specifier);
Access specifier is a mode that determines the mode of operation of Random Access File. “r” indicates for read only and “rw” indicates both for read and write. Further, there is a method called seek() that can be used to set the current position in the file. Seek() method justifies the name Random File. The syntax for seek() is: void seek(long pos) throws IOException.
There is also a provision to set the length of the Random file: void setlength(long n) throws IOException, sets the length of random files. If there are additional entries, they are ignored.
Example 21.5: RandomAccess.Java A Program to Show Use Java's File Class
1. package com.oops.chap21;
2. import java.io.*;
3. public class RandomAccess {
4. public static void main(String[] args)throws IOException {
5. //create the object for RandomFile
6. RandomAccessFile randfile = new RandomAccessFile(“raf.dat ”,”rw”);
7. try {
8. int idNo=50595;float sal =20000.00F;boolean malefemale= true;
9. char cadre = ‘S’;
10. randfile.writeInt(idNo);
11. randfile.writeDouble(sal);
12. randfile.writeChar(cadre);
13. // go to beginning of file
14. randfile.seek(0);
15. System.out.println(“idno :”+ randfile.readInt());
16. System.out.println(“Salary :”+ randfile.readDouble());
17. System.out.println(“Cadre :”+ randfile.readChar());
18. randfile.seek(randfile.length());//go to end of file
19. randfile.writeBoolean(malefemale);
20. randfile.seek(3);
21. System.out.println(“Malefemale :”+ randfile.readBoolean());
22. randfile.close();
23. }catch( IOException e){}
24. }// end of main
25. }// end of class
Output : id no :50595
Salary :20000.0
Cadre :S
Malefemale :true
Line No. 6: | RandomAccessFile randfile = new RandomAccessFile(“raf.dat”,”rw”); opens random file in read write mode. |
Line Nos. 10–12: | write int, char an double data on to Random file by randfile.write method |
Line Nos. 15–17: | display the data written on to random file by read command. |
Line No. 18: | randfile.seek(randfile.length());// go to end of file |
Serialization means storing objects on to file. De-serialization means the reverse of serialization and it means getting objects from file to class object in memory. The file to be serialized has to implement an interface called Serializable. Storing an object in a file and reading back object involves object Streams such as ObjectOutputStream and ObjectInputStream. The steps involved are shown below.
Step 1: | define a class & create an object class Student implements Serializable{{private : idNo; String name;} Student std=new Student() |
Step 2: | Use FileOutputStream: FileOutputStream fosobj= new FileOutputStream(“std,dat”) |
Step 3: | Use ObjectOutputStream : ObjectOutputStream objoutstream = new ObjectOutputStream( fosobj); |
Step 4: | Write on to file using writeObject() method of FileOutputStream |
Note that Serializable interface has no methods at all. It is used by Java to mark the file as Serializable, i.e., file to be written on to file. Static variables cannot be serialized.
Step 1: | define a class & create an object class Student implements Serializable{{private : idNo; String name;} Student std=new Student() |
Step 2: | Use FileInputStream: FileInputStream fisobj= new FileinputStream(“std.dat”) |
Step 3: | Use ObjectInputStream: ObjectInputStream objinstream = new ObjectInputStream(fisobj) |
Step 4: | Read file using readObject() method of FileInputStream Student std = ( Student) objinstream.readObject() |
Example 21.6: SerializableDemo.Java A Program to Show Serialization and Deserialization of Objects
1. package com.oops.chap21;
2. import java.io.*;
3. class Student implements Serializable {
4. // member data or attributes
5. private int idNo = 50595;
6. private double totalMarks=990.0;
7. private String grade=”A”;
8. public double getMarks(){ return totalMarks;}
9. public int getIdNo(){ return idNo;}
10. public String getGrade(){ return grade;}
11. public void DisplayData(Student std) {
12. System.out.println(“Details from Student are :”);
13. System.out.println(“idNo:” + std.getIdNo());
14. System.out.println(“Total Marks:” + std.getMarks());
15. System.out.println(„Grade:“ + std.getGrade());
16. }//end DisplayData
17. }// end of class
18. // Driver class
19. class SerializableDemo {
20. public static void main(String[] args)throws IOException{
21. // create an object of Student
22. Student std = new Student();
23. System.out.println(“Displaying Data from Student class…..”);
24. std.DisplayData(std);
25. FileOutputStream fosobj= new FileOutputStream(“Stdobj.dat”);
26. ObjectOutputStream objoutstream = new ObjectOutputStream (fosobj);
27. objoutstream.writeObject(std);
28. objoutstream.close();
29. System.out.println(“Reading from Serialized Object Student….”);
30. FileInputStream fisobj= new FileInputStream(“Stdobj.dat”);
31. ObjectInputStream objinstream = new ObjectInputStream (fisobj);
32. try{
33. std =(Student)objinstream.readObject();
34. }catch(ClassNotFoundException e){}
35. std.DisplayData(std);
36. objinstream.close();
37. }
38. }//end of class Student2bDemo
Output : Displaying Data from Student class…..
Details from Student are : idNo:50595
Total Marks:990.0 Grade:A
Reading from Serialized Object Student….
Details from Student are : idNo:50595
Total Marks:990.0 Grade:A
Line No. 6: | shows the Student file implementing Serializable interface. This implantation is mandatory. |
Line No. 25: | FileOutputStream fosobj= new FileOutputStream (“Stdobj.dat”); Creates FileOutputStream object. |
Line No. 26: | ObjectOutputStream objoutstream = new ObjectOutputStream(fosobj); creates object for ObjectOutputStrema. This is FilterOutputStream at work. |
Line No. 27: | objoutstream.writeObject(std); writes to file |
Line Nos. 30–35: | show the reverse, i.e., de-serialization. |
FileOutputStream fileout = new FileOutputStream(“data”);
DataOutputStream dosfile= new DataOutputStream(fileout);
3.14.245.167