Java I/O is centered on the concept of an I/O device, which is often a physical input or output device such as a keyboard, monitor, printer, or disk drive. Although you rarely interact with a device directly, I/O devices are always implicitly associated with I/O operations. The power of Java I/O lies in the fact that you use very similar classes and methods to read and write data regardless of the
specific I/O devices. This I/O abstraction is similar to the
graphics context[1] abstraction you learned about earlier in the course.
- Logical I/O devices
In addition to physical I/O devices, Java also supports logical I/O devices such as a block of memory or a string. Logical devices allow you to read data from strings or write data to memory, for example, as if they are physical devices. This
capability helps to unify the manner in which data is stored and retrieved and ultimately makes your job easier as a programmer.
To help underscore this point, consider the example of developing a cache program that stores commonly accessed Web information onto a hard disk. The same I/O operations used to store the information in memory could also be used to write the information to the hard disk.
Likewise, reading stored information from the hard disk would be very similar to reading it from memory.
In Java 1.1, an I/O device serves as an abstraction for input and output operations within the Java Input/Output (I/O) API, primarily using the `java.io` package. The purpose of an I/O device in this context is to facilitate reading data from input sources (e.g., files, keyboard, network sockets) and writing data to output destinations (e.g., files, console, network).
Functions of an I/O Device in Java 1.1 I/O API
-
Abstraction of Data Streams:
- Java 1.1 introduced an enhanced I/O model based on streams, which provide a unified way to handle different kinds of I/O devices.
- The
InputStream
and OutputStream
classes for byte-based data.
- The
Reader
and Writer
classes for character-based data (introduced in Java 1.1 to support Unicode).
-
Handling File Input and Output:
FileInputStream
and FileOutputStream
for reading and writing files in byte format.
FileReader
and FileWriter
for reading and writing files in character format.
-
Interfacing with the Console (Standard I/O):
System.in
(for reading input from the keyboard).
System.out
(for printing output to the console).
System.err
(for error messages).
-
Buffered I/O for Performance Optimization:
BufferedInputStream
and BufferedOutputStream
for improving efficiency when reading/writing large amounts of data.
BufferedReader
and BufferedWriter
for character-based buffered I/O.
-
Support for Object Serialization (New in Java 1.1):
- Java 1.1 introduced object serialization with
ObjectInputStream
and ObjectOutputStream
, allowing objects to be converted into a byte stream and stored or transferred.
-
Interfacing with Network Streams:
Socket.getInputStream()
and Socket.getOutputStream()
allow network communication over TCP/IP.
-
Filter Streams for Data Processing:
FilterInputStream
and FilterOutputStream
provide additional processing like compression or encryption.
DataInputStream
and DataOutputStream
allow reading/writing primitive data types.
Example of an I/O Device in Java 1.1
Reading from a file:
import java.io.FileReader;
import java.io.IOException;
public class FileReaderExample {
public static void main(String[] args) {
try (FileReader fr = new FileReader("example.txt")) {
int character;
while ((character = fr.read()) != -1) {
System.out.print((char) character);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Conclusion In Java 1.1, an I/O device within the Java I/O API represents any external or internal source/destination of data. The API provides a stream-based architecture to handle files, console input/output, network communication, and serialized objects efficiently.