For working professionals
For fresh graduates
More
6. JDK in Java
7. C++ Vs Java
16. Java If-else
18. Loops in Java
20. For Loop in Java
45. Packages in Java
52. Java Collection
55. Generics In Java
56. Java Interfaces
59. Streams in Java
62. Thread in Java
66. Deadlock in Java
73. Applet in Java
74. Java Swing
75. Java Frameworks
77. JUnit Testing
80. Jar file in Java
81. Java Clean Code
85. Java 8 features
86. String in Java
92. HashMap in Java
97. Enum in Java
100. Hashcode in Java
104. Linked List in Java
108. Array Length in Java
110. Split in java
111. Map In Java
114. HashSet in Java
117. DateFormat in Java
120. Java List Size
121. Java APIs
127. Identifiers in Java
129. Set in Java
131. Try Catch in Java
132. Bubble Sort in Java
134. Queue in Java
141. Jagged Array in Java
143. Java String Format
144. Replace in Java
145. charAt() in Java
146. CompareTo in Java
150. parseInt in Java
152. Abstraction in Java
153. String Input in Java
155. instanceof in Java
156. Math Floor in Java
157. Selection Sort Java
158. int to char in Java
163. Deque in Java
171. Trim in Java
172. RxJava
173. Recursion in Java
174. HashSet Java
176. Square Root in Java
189. Javafx
With the rise of cloud computing, big data, and AI-driven applications, efficient file handling in Java remains a critical skill for developers. Java provides robust support for file operations, enabling seamless reading, writing, and management of data across local and distributed systems.
This tutorial will help you understand how to handle files effectively in Java, using modern best practices to ensure performance, security, and scalability. Let’s dive in!
Improve your Java programming skills with our Software Development courses — take the next step in your learning journey!
File handling refers to the process of performing operations such as creating, reading, writing, modifying, and deleting files in a programming language. In Java, these operations are managed using built-in libraries that provide methods to interact with files seamlessly.
Here’s why it's important:
Java provides two main libraries for file handling:
1. java.io (Traditional I/O API)
Includes classes like File, FileReader, FileWriter, BufferedReader, and BufferedWriter. Best for basic file operations but can be slower for large-scale data processing.
2. java.nio (Non-blocking I/O API)
Includes classes like Files, Paths, ByteBuffer, and FileChannel. Designed for more advanced and performant file handling, java.nio provides improved performance, non-blocking I/O, and efficient handling of large files.
It is still widely used in modern Java applications for handling complex I/O tasks.
Also Read: Exploring the 14 Key Advantages of Java: Why It Remains a Developer's Top Choice in 2025
Understanding these classes is key to writing optimized file-handling code in Java. Now, let’s dive into basic file operations and how to implement them.
File handling in Java allows developers to create, modify, and delete files efficiently. Using Java’s built-in file-handling classes, we can perform these operations with ease. Below, we explore the fundamental file operations, including creating, writing, reading, and deleting files in Java.
To create a file in Java, we use the File class from the java.io package. The createNewFile() method attempts to create a new file and returns true if successful.
Example:
import java.io.File;
import java.io.IOException;
public class CreateFileExample {
public static void main(String[] args) {
try {
File myFile = new File("example.txt");
if (myFile.createNewFile()) {
System.out.println("File created: " + myFile.getName());
} else {
System.out.println("File already exists.");
}
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
This ensures that a new file is created if it does not already exist. In this example, the File object is created using the file name 'example.txt'. createNewFile() tries to create the file. If it already exists, it returns false. If an error occurs (e.g., insufficient permissions), an IOException is caught and printed.
Possible Outputs:
File created: example.txt
or
File already exists.
To write content to a file, Java provides FileWriter for direct writing and BufferedWriter for efficient, buffered writing.
Example using FileWriter:
import java.io.FileWriter;
import java.io.IOException;
public class WriteFileExample {
public static void main(String[] args) {
try {
FileWriter writer = new FileWriter("example.txt");
writer.write("Hello, this is a test file!");
writer.close();
System.out.println("Successfully wrote to the file.");
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
In this example, FileWriter writes data to example.txt. If the file doesn’t exist, it is created automatically. The write() method adds text, and close() ensures data is saved.
Expected Output:
Successfully wrote to the file.
After execution, the file example.txt contains:
Hello, this is a test file!
Example using BufferedWriter:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriteExample {
public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("example.txt", true))) {
writer.write("Appending this line using BufferedWriter.");
writer.newLine();
System.out.println("Successfully appended text.");
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
In this example, BufferedWriter enhances performance, especially when writing large text files. true in FileWriter("example.txt", true) enables append mode, whereas newLine() ensures the new text appears on a new line.
It is generally preferred for writing text files when dealing with many small writes, as it improves performance by reducing the number of I/O operations.
However, for large files, using larger buffers or memory-mapped files (via java.nio) is often a better option to optimize performance, as they allow for more efficient reading and writing of large data blocks at once.
Expected Output:
Successfully appended text.
After execution, example.txt now contains:
Hello, this is a test file!
Appending this line using BufferedWriter.
To read data from a file, you use FileReader for character-based reading and BufferedReader for efficient line-by-line reading.
Example using FileReader:
import java.io.FileReader;
import java.io.IOException;
public class ReadFileExample {
public static void main(String[] args) {
try (FileReader reader = new FileReader("example.txt")) {
int character;
while ((character = reader.read()) != -1) {
System.out.print((char) character);
}
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
In this example, FileReader reads the file character by character. The while loop continues until the end of the file (-1).
Expected Output:
Hello, this is a test file!
Appending this line using BufferedWriter.
Example using BufferedReader:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReadExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
In this example, BufferedReader reads the file line by line instead of character by character. It is more efficient than FileReader for large files.
It is recommended for reading text files efficiently, especially when reading line-by-line, as it reduces the number of I/O operations by buffering the input. However, for extremely large files, it may not always be the most efficient choice, as it still requires reading the file sequentially.
For large binary files, using the java.nio.file package (e.g., FileChannel and ByteBuffer) would be more efficient, as it allows for non-blocking, high-performance I/O operations and memory-mapped file handling, which are better suited for large datasets.
Expected Output:
Hello, this is a test file!
Appending this line using BufferedWriter.
Deleting a File (delete() Method)
To delete a file, you use the delete() method of the File class.
Example:
import java.io.File;
public class DeleteFileExample {
public static void main(String[] args) {
File myFile = new File("example.txt");
if (myFile.delete()) {
System.out.println("File deleted: " + myFile.getName());
} else {
System.out.println("Failed to delete the file.");
}
}
}
Ensure the file is closed before attempting to delete it to avoid errors. In this example, delete() removes example.txt if it exists. If the file is open in another program, the deletion may fail.
Possible Outputs:
File deleted: example.txt
or
Failed to delete the file.
These basic file operations—creating, writing, reading, and deleting files—are fundamental to file handling in Java.
Also Read: Abstract Class and Methods in Java: Key Concepts, Examples and Best Practices
Now, let’s explore advanced techniques for handling large files and working with streams efficiently.
Beyond basic file operations, Java provides stream-based file handling and the java.nio.file package for efficient data processing. These advanced techniques help handle large files, binary data, and non-blocking I/O operations for better performance.
Java uses byte streams for handling binary files such as images, audio, and video. The FileInputStream and FileOutputStream classes allow reading and writing files at the byte level.
Example: Writing Binary Data with FileOutputStream
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamExample {
public static void main(String[] args) {
String data = "This is a binary file example.";
try (FileOutputStream fos = new FileOutputStream("binaryfile.dat")) {
fos.write(data.getBytes());
System.out.println("Binary data written successfully.");
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
In this example, FileOutputStream writes binary data to binaryfile.dat. getBytes() converts the string into a byte array before writing. try-with-resources ensures the stream is closed properly.
Expected Output:
Binary data written successfully.
Example: Reading Binary Data with FileInputStream
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("binaryfile.dat")) {
int byteData;
while ((byteData = fis.read()) != -1) {
System.out.print((char) byteData);
}
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
FileInputStream reads binary data one byte at a time. Each byte is converted back to a character and displayed.
Expected Output:
This is a binary file example.
File Handling in Java involves managing both binary and text files efficiently. Binary files store non-text data such as images, videos, and serialized objects. To process them, FileInputStream and FileOutputStream handle byte-level operations, ensuring proper encoding for structured formats.
In contrast, text files store human-readable data like .txt, .csv, and .json. For efficient handling, BufferedReader and BufferedWriter are preferred, with UTF-8 encoding ensuring compatibility across systems.
Example: Copying a Binary File (Image or Any File)
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyBinaryFileExample {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("source.jpg");
FileOutputStream fos = new FileOutputStream("copy.jpg")) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
System.out.println("File copied successfully.");
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
In this example, the file is read in chunks of 1024 bytes for efficiency. FileInputStream reads the source file, and FileOutputStream writes it to a new file. This method works for any binary file (images, audio, video, etc.).
Expected Output:
File copied successfully.
The java.nio.file package provides faster and more flexible file operations using Path and Files classes.
Example: Creating a File with Files.createFile()
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
public class NIOCreateFileExample {
public static void main(String[] args) {
Path path = Paths.get("nio_example.txt");
try {
Files.createFile(path);
System.out.println("File created successfully.");
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
In this example, Paths.get("filename") creates a Path object instead of a File object. Files.createFile() creates the file more concisely than File.createNewFile().
Expected Output:
File created successfully.
Example: Reading a File with Files.readAllLines()
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.List;
public class NIOReadFileExample {
public static void main(String[] args) {
Path path = Paths.get("nio_example.txt");
try {
List<String> lines = Files.readAllLines(path);
for (String line : lines) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
In this example, Files.readAllLines() reads all lines into a List<String>. More memory-efficient than BufferedReader for small files.
Expected Output:
(Displays file content line by line.)
Example: Deleting a File with Files.delete()
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
public class NIODeleteFileExample {
public static void main(String[] args) {
Path path = Paths.get("nio_example.txt");
try {
Files.delete(path);
System.out.println("File deleted successfully.");
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
}
}
In this example, Files.delete() deletes a file more safely than File.delete(). It throws an exception if the file doesn’t exist, preventing silent failures.
Expected Output:
File deleted successfully.
These advanced techniques help boost performance, reduce memory usage, and improve maintainability in real-world applications.
Also Read: OOPS Concept in Java Explained for Beginners
Now, let’s explore exception handling in file operations to ensure error-free execution.
Handling files in Java comes with potential errors, such as missing files, permission issues, or interrupted read/write processes. Proper exception handling ensures smooth execution and prevents application crashes. Let’s explore common exceptions, best practices, and how to use try-with-resources for safer file handling.
FileNotFoundException: Occurs when trying to access a file that does not exist or if the program lacks read permissions.
Example:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileNotFoundExample {
public static void main(String[] args) {
try {
File file = new File("nonexistent.txt");
Scanner scanner = new Scanner(file); // Triggers FileNotFoundException
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
scanner.close();
} catch (FileNotFoundException e) {
System.out.println("Error: File not found!");
e.printStackTrace();
}
}
}
Expected Output:
Error: File not found!
Fix: Ensure the file exists before accessing it using file.exists().
IOException: A general exception for I/O errors, such as read/write failures or permission issues.
Example:
import java.io.FileWriter;
import java.io.IOException;
public class IOExceptionExample {
public static void main(String[] args) {
try {
FileWriter writer = new FileWriter("/restricted/file.txt"); // No permission
writer.write("This will fail!");
writer.close();
} catch (IOException e) {
System.out.println("Error: Unable to write to file!");
e.printStackTrace();
}
}
}
Expected Output:
Error: Unable to write to file!
Fix: Ensure the program has the necessary file system permissions.
In Java, try-with-resources is a feature that automatically closes file streams and other resources once they are no longer needed. This helps prevent resource leaks and makes the code cleaner.
How It Works:
Example: Safe File Handling with Try-with-Resources
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("Error: Unable to read file.");
e.printStackTrace();
}
}
}
In this example, the BufferedReader is declared inside the try() statement. If an exception occurs, Java automatically closes the resource when exiting the block. The catch block handles IOException, which occurs if the file is missing or unreadable.
Expected Output (if example.txt contains text):
Hello, this is a test file.
Appending this line using BufferedWriter.
Expected Output (if the file does not exist):
Error: Unable to read file.
java.io.FileNotFoundException: example.txt (No such file or directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:219)
at java.io.FileInputStream.<init>(FileInputStream.java:157)
at java.io.FileReader.<init>(FileReader.java:75)
Why Use Try-with-Resources?
Try-with-resources is the recommended approach for handling files safely in Java!
Also Read: Comprehensive Guide to Exception Handling in Java: Best Practices and Examples
By handling common exceptions, using try-with-resources, and following file handling best practices in Java, developers can create robust and error-free file-handling applications.
It’s essential to follow file handling best practices in Java to ensure efficient performance, especially when dealing with large datasets or complex file operations.
Efficient file handling best practices in Java result in optimal performance when reading or writing files, especially when working with large datasets or real-time systems. Below are some best practices for handling files efficiently:
1. Use Buffered I/O: BufferedReader and BufferedWriter should be used when reading and writing text files. They use buffers to minimize the number of I/O operations, improving performance when dealing with large files.
Similarly, use BufferedInputStream and BufferedOutputStream for binary files.
2. Read and Write in Chunks: For large files, avoid reading or writing data one byte/character at a time. Instead, read or write in chunks using arrays or buffers to significantly improve performance.
byte[] buffer = new byte[1024]; // Buffer of 1024 bytes
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
3. Use Memory Mapped Files: Java’s java.nio package offers memory-mapped files, which allow files to be mapped into memory directly. This technique is particularly useful for large files as it enables random access to parts of the file without loading the entire file into memory.
4. Close Resources Properly: Always close file streams using try-with-resources or manually in a finally block to avoid resource leaks.
Java provides two primary packages for file handling: java.io and java.nio (New I/O). Choosing between these depends on your specific needs:
Criteria | java.io (Traditional I/O) | java.nio (New I/O) |
Best For | Simple applications and smaller text files. | Performance-intensive applications and large binary files. |
I/O Model | Blocking I/O (synchronous). | Non-blocking I/O (asynchronous). |
File Handling | Provides classes like FileReader, FileWriter, BufferedReader, and BufferedWriter. | Provides classes like FileChannel, ByteBuffer, Files, and Path. |
Performance | Slower for large files and complex operations. | Faster for large files and complex file operations. |
File Operations | Suitable for simple read/write operations on small text files. | Suitable for large file handling, memory-mapped files, and file channels. |
Concurrency | Limited concurrency, blocking operations. | High concurrency with non-blocking, asynchronous operations. |
Use Case | Small-scale or legacy applications that require basic file operations. | Modern applications requiring scalable, non-blocking I/O for handling large volumes of data. |
When to Use | Simple text files or small datasets. | Large binary files, random access to files, and when using memory-mapped files. |
This table helps quickly compare the capabilities of java.io and java.nio so you can choose the best package based on your application’s requirements.
When dealing with large files, performance can become a significant concern. Here are some strategies to handle large files efficiently by following the file handling best practices in Java:
1. Use Memory-Mapped Files: As mentioned earlier, memory-mapped files allow files to be loaded directly into memory, enabling faster access to large files. The file content can be accessed as if it were part of memory, without loading the entire file at once.
RandomAccessFile file = new RandomAccessFile("largefile.dat", "rw");
FileChannel channel = file.getChannel();
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
2. Parallel Processing: For extremely large files, divide the file into chunks and process them in parallel. This can be done by splitting the file into smaller segments and processing them concurrently in different threads, improving speed.
However, this is only applicable to certain types of files, like log files or data files that are line-based.
3. Use Efficient Buffering: When reading or writing large files, use larger buffers. For example, instead of using a buffer size of 8 KB, consider using a buffer size of 64 KB or more. Larger buffers reduce the number of read and write operations, improving speed.
4. Avoid Reading the Entire File into Memory: Avoid using methods that load the entire file into memory at once (like readAllBytes() or readAllLines()) for large files, as it can lead to OutOfMemoryError. Instead, read and process files in streams or chunks.
5. Consider Compression: When dealing with massive files, compression can help reduce file size, making I/O operations faster. Use tools like gzip to compress files before writing and decompress them during reading.
Efficient file handling is critical for performance when working with large datasets. By following best practices such as using Buffered I/O, choosing the right package between java.io and java.nio, and implementing strategies for handling large files, you can ensure optimal performance and scalability.
This will lead to faster, more efficient applications that can handle large-scale file operations seamlessly.
Also Read: Careers in Java: How to Make a Successful Career in Java in 2025
To solidify your understanding of file handling best practices in Java, test your knowledge with a quiz. It’ll help reinforce the concepts discussed throughout the tutorial and ensure you're ready to apply them in your projects.
Assess your understanding of file handling techniques, best practices, and common mistakes in Java by answering the following multiple-choice questions. Dive in!
1. Which class is used to read data from a file in Java?
a) FileWriter
b) BufferedWriter
c) FileReader
d) FileOutputStream
2. What does File.createNewFile() return if the file already exists?
a) true
b) false
c) null
d) A compilation error
3. Which method is used to delete a file in Java?
a) remove()
b) deleteFile()
c) delete()
d) deleteFile()
4. What is the primary benefit of using BufferedReader and BufferedWriter over FileReader and FileWriter?
a) They are more efficient for reading and writing large files.
b) They allow for asynchronous file operations.
c) They handle binary data.
d) They automatically close files after use.
5. Which class should you use for binary file operations in Java?
a) FileReader
b) BufferedReader
c) FileInputStream
d) FileWriter
6. How does try-with-resources help in file handling?
a) It automatically compresses files.
b) It manages resources efficiently by automatically closing them after use.
c) It improves file read/write performance.
d) It ensures thread safety in file operations.
7. When should you use java.nio.file over java.io for file handling?
a) When working with small text files only.
b) When requiring non-blocking, high-performance file operations.
c) When writing to text files in UTF-8 encoding.
d) When working with legacy systems.
8. What happens if you attempt to write to a file without appropriate write permissions in Java?
a) The program will compile but throw a runtime error.
b) A FileNotFoundException will be thrown.
c) An IOException will be thrown.
d) The data will be written successfully.
9. Which of the following is NOT an advantage of using java.nio.file package over java.io?
a) Non-blocking I/O operations
b) Memory-mapped file support
c) Simpler syntax for basic file operations
d) Better performance with large files
10. What is the best way to handle file read and write errors in Java?
a) Ignore the error and continue execution.
b) Print the error message and terminate the program.
c) Use try-catch blocks to handle exceptions gracefully.
d) Retry the file operation multiple times until successful.
This quiz ensures you have a solid understanding of file handling in Java, the differences between java.io and java.nio, and how to manage file operations efficiently and safely.
Also Read: Top 8 Reasons Why Java Is So Popular and Widely Used in 2025
You can continue expanding your skills in Java with upGrad, which will help you deepen your understanding of advanced Java concepts and real-world applications.
upGrad’s courses provide expert training in Java programming, focusing on file handling, best practices, and performance optimization. Gain hands-on experience in managing files efficiently, handling exceptions, and building high-performance Java applications.
Below are some relevant upGrad courses:
You can also get personalized career counseling with upGrad to guide your career path, or visit your nearest upGrad center and start hands-on training today!
Similar Reads:
Ensure the file path is correct and that the program has the necessary read permissions. Double-check for typos and verify that the path is accessible from the application's working directory.
The program may be reading the file line by line or byte by byte. Use BufferedReader/BufferedWriter for text files and consider reading in larger chunks to improve performance. Memory-mapped files in java.nio can also speed up large file handling.
No, binary files require byte-based streams (FileInputStream and FileOutputStream), while text files use character-based streams (FileReader and FileWriter). Using the wrong class will lead to encoding issues and data corruption.
You can catch an IOException and either prompt the user to retry or log the error. Java doesn't provide a direct way to check if a file is locked, but catching exceptions and handling them gracefully is the best approach.
File.createNewFile() is part of the older java.io API and creates a file if it doesn’t already exist. On the other hand, Files.createFile() is part of the java.nio.file package and offers better performance and more flexibility when working with file paths and attributes.
try-with-resources ensures that resources are automatically closed at the end of the block, even in case of exceptions. This reduces the risk of resource leaks and makes your code cleaner and more maintainable.
For large files, avoid loading the entire file into memory. Use streams to process the file chunk by chunk or line by line. In extreme cases, consider using memory-mapped files via java.nio to improve efficiency.
To append data to a file, use the FileWriter constructor with the second argument set to true (new FileWriter("file.txt", true)). Alternatively, BufferedWriter can be used in append mode to efficiently add new content.
Always specify the encoding when dealing with text files by using InputStreamReader and OutputStreamWriter with the desired charset (e.g., UTF-8). For FileReader and FileWriter, the default system encoding may cause issues, so explicitly set it.
Use the exists() method of the File class or Files.exists(path) in java.nio to verify if the file exists before attempting to read or write. This helps prevent FileNotFoundException errors.
While java.nio offers superior performance for large files and non-blocking I/O, it has a steeper learning curve and is more complex than the traditional java.io API. Additionally, some older systems or libraries may not fully support the new I/O package.
Take the Free Quiz on Java
Answer quick questions and assess your Java knowledge
Author
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918045604032
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.