IO Streams (File IO)

Java 12 min min read Updated: Mar 31, 2026 Intermediate
IO Streams (File IO)
Intermediate Topic 6 of 14

IO Streams (File IO)

In Java, programs often need to interact with files and external data sources. A program may need to read data from a file, write reports into a file, copy images, save logs, store user input, or load configuration values. All of these tasks come under Input and Output, commonly called I/O.

Java provides a rich I/O API to handle such operations using streams. Understanding streams and file I/O is essential because almost every real-world application works with external data in some form.

Key Concept: Java I/O streams provide a way to read data from a source and write data to a destination. File I/O specifically deals with reading from and writing to files.

What is I/O in Java?

I/O stands for Input and Output.

  • Input means taking data into the program
  • Output means sending data out of the program

Examples:

  • reading text from a file
  • writing content into a file
  • reading keyboard input
  • sending output to console or printer

What is a Stream?

A stream is a flow of data between a program and a data source or destination.

In simple words:

  • if data is coming into the program → input stream
  • if data is going out from the program → output stream

Java treats files, keyboard, network, and memory data as streams.

Why Streams are Used

  • to provide a uniform way to handle data input and output
  • to support files, console, network, and memory operations
  • to make data reading and writing structured and reusable

Java I/O Packages

The main package for traditional I/O in Java is:

java java.io

Some file-related and modern I/O utilities are also found in:

java java.nio java.nio.file

In this tutorial, the main focus is on the traditional I/O stream model from java.io.

Types of Streams in Java

Streams in Java are broadly divided into:

  • Byte Streams
  • Character Streams

1. Byte Streams

Byte streams are used to read and write raw binary data. They are suitable for files like:

  • images
  • audio files
  • videos
  • PDFs
  • binary data

Main parent classes:

  • InputStream
  • OutputStream

2. Character Streams

Character streams are used to read and write text data. They are suitable for:

  • text files
  • source code files
  • configuration files
  • CSV and log files

Main parent classes:

  • Reader
  • Writer

Difference Between Byte Streams and Character Streams

Point Byte Streams Character Streams
Data type Raw bytes Characters / text
Use case Binary files Text files
Main classes InputStream / OutputStream Reader / Writer

File I/O in Java

File I/O means reading data from a file and writing data into a file.

Java provides many classes for file handling, such as:

  • File
  • FileInputStream
  • FileOutputStream
  • FileReader
  • FileWriter
  • BufferedReader
  • BufferedWriter
  • PrintWriter

File Class

The File class is used to represent a file or directory path. It does not itself read or write content, but it helps in checking, creating, or managing file-related information.

Example

java import java.io.File; public class Main { public static void main(String[] args) { File file = new File("sample.txt"); System.out.println(file.exists()); System.out.println(file.getName()); System.out.println(file.getAbsolutePath()); } }

Creating a File

The createNewFile() method can be used to create a new file.

java import java.io.File; import java.io.IOException; public class Main { public static void main(String[] args) throws IOException { File file = new File("sample.txt"); if (file.createNewFile()) { System.out.println("File created"); } else { System.out.println("File already exists"); } } }

Reading File Using FileInputStream

FileInputStream is a byte stream class used to read binary data from a file.

Example

java import java.io.FileInputStream; public class Main { public static void main(String[] args) throws Exception { FileInputStream fis = new FileInputStream("sample.txt"); int data; while ((data = fis.read()) != -1) { System.out.print((char) data); } fis.close(); } }

Here:

  • read() returns one byte at a time
  • -1 means end of file

Writing File Using FileOutputStream

FileOutputStream is used to write binary data into a file.

Example

java import java.io.FileOutputStream; public class Main { public static void main(String[] args) throws Exception { FileOutputStream fos = new FileOutputStream("sample.txt"); String text = "Hello Java File IO"; fos.write(text.getBytes()); fos.close(); System.out.println("Data written"); } }

Reading Text File Using FileReader

FileReader is a character stream class used for reading text files.

java import java.io.FileReader; public class Main { public static void main(String[] args) throws Exception { FileReader fr = new FileReader("sample.txt"); int ch; while ((ch = fr.read()) != -1) { System.out.print((char) ch); } fr.close(); } }

Writing Text File Using FileWriter

FileWriter is a character stream class used to write text data into files.

java import java.io.FileWriter; public class Main { public static void main(String[] args) throws Exception { FileWriter fw = new FileWriter("sample.txt"); fw.write("Java File Handling Example"); fw.close(); System.out.println("File written successfully"); } }

Appending Data to File

By default, FileWriter overwrites file content. To append data, pass true as the second argument.

java FileWriter fw = new FileWriter("sample.txt", true); fw.write("\nNew line added"); fw.close();

Buffered Streams

Buffered streams improve performance by reducing the number of direct disk access operations. They read and write data in larger chunks.

Common buffered classes:

  • BufferedInputStream
  • BufferedOutputStream
  • BufferedReader
  • BufferedWriter

Reading File Using BufferedReader

BufferedReader is commonly used to read text line by line.

java import java.io.BufferedReader; import java.io.FileReader; public class Main { public static void main(String[] args) throws Exception { BufferedReader br = new BufferedReader(new FileReader("sample.txt")); String line; while ((line = br.readLine()) != null) { System.out.println(line); } br.close(); } }

This is more efficient and convenient than reading one character at a time.

Writing File Using BufferedWriter

java import java.io.BufferedWriter; import java.io.FileWriter; public class Main { public static void main(String[] args) throws Exception { BufferedWriter bw = new BufferedWriter(new FileWriter("sample.txt")); bw.write("First line"); bw.newLine(); bw.write("Second line"); bw.close(); } }

Using PrintWriter

PrintWriter is useful for writing formatted text data to a file.

java import java.io.PrintWriter; public class Main { public static void main(String[] args) throws Exception { PrintWriter pw = new PrintWriter("sample.txt"); pw.println("Java"); pw.println("Python"); pw.println("C++"); pw.close(); } }

Copying a File

A common practical use of file I/O is copying content from one file to another.

java import java.io.FileInputStream; import java.io.FileOutputStream; public class Main { public static void main(String[] args) throws Exception { FileInputStream fis = new FileInputStream("source.txt"); FileOutputStream fos = new FileOutputStream("destination.txt"); int data; while ((data = fis.read()) != -1) { fos.write(data); } fis.close(); fos.close(); System.out.println("File copied"); } }

try-with-resources in File I/O

Java provides try-with-resources to automatically close resources like streams and readers.

This is one of the best practices in file handling.

java import java.io.BufferedReader; import java.io.FileReader; public class Main { public static void main(String[] args) throws Exception { try (BufferedReader br = new BufferedReader(new FileReader("sample.txt"))) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } } }

The file is automatically closed after the block ends.

IOException

File operations may fail due to reasons such as:

  • file not found
  • permission denied
  • invalid path
  • disk issues

These are represented through checked exceptions such as IOException.

Example

java import java.io.FileReader; public class Main { public static void main(String[] args) { try { FileReader fr = new FileReader("missing.txt"); } catch (Exception e) { System.out.println("File not found"); } } }

File Path Types

Java can work with two types of file paths:

  • relative path
  • absolute path

Relative Path

java File file = new File("sample.txt");

Absolute Path

java File file = new File("C:\\Users\\User\\Documents\\sample.txt");

Relative paths depend on the current working directory, while absolute paths point to the exact location.

Character Encoding Note

Text files depend on character encoding. Traditional classes like FileReader use the default platform encoding. In advanced applications, developers often prefer more explicit control over encoding.

For basic learning, FileReader and FileWriter are enough, but in professional projects, encoding awareness is very important.

Real-World File I/O Examples

1. Saving User Registration Logs

java FileWriter fw = new FileWriter("users.log", true); fw.write("User Amit registered\n"); fw.close();

2. Reading Configuration File

java BufferedReader br = new BufferedReader(new FileReader("config.txt")); String line = br.readLine(); br.close();

3. Copying Report File

java FileInputStream fis = new FileInputStream("report.pdf"); FileOutputStream fos = new FileOutputStream("backup_report.pdf");

Common Mistakes

  • forgetting to close streams
  • using byte streams for text when character streams are more suitable
  • not handling file exceptions properly
  • confusing relative and absolute file paths
  • overwriting file content when append mode was intended

Best Practices

  • use character streams for text data
  • use byte streams for binary data
  • prefer buffered streams for efficiency
  • use try-with-resources for automatic cleanup
  • handle exceptions meaningfully
  • avoid hardcoding paths when possible

Interview-Oriented Points

  • I/O stands for Input and Output
  • Streams are flows of data between program and source/destination
  • Byte streams handle binary data, character streams handle text
  • FileInputStream and FileOutputStream are byte stream classes
  • FileReader and FileWriter are character stream classes
  • BufferedReader reads text line by line efficiently
  • try-with-resources automatically closes streams
  • File-related exceptions are generally checked exceptions

Conclusion

I/O streams and file handling are core parts of Java programming because almost every real application works with external data. Java provides a flexible and powerful stream-based model for reading and writing both text and binary files.

Understanding when to use byte streams, character streams, buffered streams, and resource management practices is essential for writing correct and efficient Java programs.

Quick Summary: Java I/O streams allow programs to read from and write to files and other data sources. Byte streams handle binary data, character streams handle text, and buffered streams improve performance.

Get Newsletter

Subscibe to our newsletter and we will notify you about the newest updates on Edugators