Back to course

Input and Output Streams (Byte Streams vs. Character Streams)

Java Mastery: From Zero to Professional Developer (50-Lesson Journey)

Lesson 44: Input and Output Streams

Java I/O is based on the concept of streams, which represent a sequence of data flowing from a source (Input Stream) to a destination (Output Stream).

1. Byte Streams

  • Handle raw binary data (e.g., images, sound, serialized objects).
  • Base classes: InputStream (read) and OutputStream (write).
  • Concrete classes: FileInputStream, FileOutputStream.

java // Example: Copying data byte by byte (inefficient, for illustration) try (InputStream input = new FileInputStream("source.dat"); OutputStream output = new FileOutputStream("target.dat")) {

int data; 
while ((data = input.read()) != -1) { // Reads one byte
    output.write(data);
}

} catch (IOException e) { // Handle exception }

2. Character Streams

  • Handle text data (characters), using encoding like UTF-8 or ASCII.
  • Base classes: Reader (read) and Writer (write).
  • Concrete classes: FileReader, FileWriter.

java // Example: Reading text try (Reader reader = new FileReader("config.txt")) { int charCode; while ((charCode = reader.read()) != -1) { System.out.print((char) charCode); } } catch (IOException e) { /* ... */ }

3. Buffered Streams and Decorator Pattern

To improve performance, streams are often wrapped in buffered streams. Buffering reads large chunks of data from the disk at once, reducing I/O operations.

  • BufferedReader/BufferedWriter (Character)
  • BufferedInputStream/BufferedOutputStream (Byte)

java // Using a BufferedReader to efficiently read lines of text try (BufferedReader br = new BufferedReader(new FileReader("large.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException e) { /* ... */ }

Try-with-Resources (Crucial): Notice the use of the try ( ... ) syntax. This ensures that streams are automatically and safely closed, even if an exception occurs.