Byte streams, character streams, buffered streams, data streams and object streams are different data reading mechanisms for File IO. Each of the stream has a unique purpose to serve. In this article, we explore details of these streams. Also, we try to find when to use which stream.
Byte Streams:
java.io.FileInputStream and java.io.FileOutputStream are the two classes for reading and writing purpose from/to a file. These classes extend from InputStream and OutputStream respectively. Data read by these classes is in low level format i.e. binary format. Hence if you have following code, then it will return value as int (which is the converted byte).
FileInputStream ins = new FileInputStream(“myfile.txt”);
int c = ins.read();
Similarly FileOutputStream writes data in binary format. Hence when you really want to deal with file contents in binary mode, such as bit wise operations, logical operations etc., then go for these classes. Otherwise it is better to choose from other file readers/writers.
Character Streams:
Here everything is handled in terms of characters. java.io.FileReader and java.io.FileWriter are the classes that handle character input from files and character output to the file. These classes are subclasses of java.io.Reader and java.io.Writer respectively.Any data read or written is converted into characters. Character encoding becomes important here otherwise you may end up in garbage conversion of some of the characters not available in default encoding, which is generally 8-bit superset of ASCII. As we are dealing with file in character mode, it is possible to handle contents line by line. Hence FileReader.readLine() method is available to read a line. Similarly FileWriter.write method is there to write a line to file.
All above classes read/write data directly from the underlying operation system. Hence each read/write call involves interaction with native APIs and subsequently with underlying operating system. This means network access, disc access, etc. This is not very performing implementation. Hence following set of classes are the solution to this problem.
Buffered Streams:
Buffered I/O is different because it is based on reading/writing data from memory (called as buffer) instead of directly from the underlying system. Now the interaction with disc is dependent on when you want more in buffer, or when you want to flush something out of buffer. By this mechanism we can control the number of calls being made to the underlying operating system.We can also wrap above classes by buffered readers to avail buffering facility. Code snippet like this will help us to get advantage of buffering with previous classes also.
bufferedInput = new BufferedReader(new FileReader(“myfile.txt”));
Output classes mostly support autoflush to empty buffer on disc periodically. Classes like PrintWriter also provide manual flushing ability so that we can optimize usage of these classes. You can find this feature effectively implemented in large response from client to server using http request-response model.
Data Streams:
These classes have got special function to do. Data stream classed provide special methods to read/write primitive data types. If we do not handle primitive data types in a special way and treat them as objects, then there is possibility of data loss during automatic conversions. To avoid this, these classes can be used. java.io.DataInputStream and java.io.DataOutputStream are two important classes. DataInputStream exposes methods like readInt(), readDouble(), etc. to read primitives, while DataOutputStream offeres similar methods writeInt(), writeDouble(), etc. to write primitives.
Object Streams:
java.io.ObjectInputStream and java.io.ObjectOutputStream are used to perform read and write of objects. Object read/write involves serialization/de-serialization of data, hence it involves special handling. (Most of the classes under object streams support serialization/de-serialization of data). There is complex logic involved in reading and writing of objects. Reason behind complexity are – objects have type hence regeneration should also result in type match with original object. Second is object have hierarchies. These hierarchies should also be satisfied in object streams transfer.
Summary:
java.io package provides many classes to interact with files on operating systems. Usually JVM interfaces with operating system, in other words, it shields program from the complexities of operating system interactions. But File handling is the area where the program has to directly deal with underlying operating system. java.io package offers many classes which serve general as well as specific purposes in file dealing. By selecting correct class, we can write better performing applications.
No comments:
Post a Comment