Java File Handling - Complete Tutorial
Master Java File I/O: Learn to read, write, create, delete files and directories using File, FileReader, FileWriter, BufferedReader, BufferedWriter, FileInputStream, FileOutputStream classes with practical examples.
File Class
File & Directory Operations
Character Streams
Text File Handling
Byte Streams
Binary File Handling
Buffered I/O
High Performance
1. Introduction to Java File Handling
File Handling in Java is crucial for persistent data storage and data exchange between applications. Java provides comprehensive I/O capabilities through the java.io package for reading from and writing to files.
Why File Handling?
- Data Persistence: Store data beyond program execution
- Configuration Files: Store application settings
- Data Logging: Record application events and errors
- Data Import/Export: Exchange data with other applications
- Backup & Recovery: Create backup files
- Large Data Processing: Handle datasets too large for memory
Java I/O Stream Types
- Byte Streams: Handle binary data (images, videos)
- Character Streams: Handle text data (UTF-16)
- Buffered Streams: Improve I/O performance
- Data Streams: Handle primitive data types
- Object Streams: Handle object serialization
- File Streams: File-specific operations
File Handling Flow
Basic file operations follow: Open Stream → Read/Write Data → Close Stream. Always close streams in finally block or use try-with-resources.
File Class
File & directory operations
Character Streams
Text file handling
Byte Streams
Binary file handling
2. The File Class
The java.io.File class represents file and directory pathnames. It provides methods to create, delete, rename files, check file properties, and list directory contents.
import java.io.File;
import java.io.IOException;
import java.util.Date;
public class FileClassExample {
public static void main(String[] args) {
// Create File object
File file = new File("example.txt");
File directory = new File("testDir");
System.out.println("=== File Information ===");
System.out.println("File name: " + file.getName());
System.out.println("Absolute path: " + file.getAbsolutePath());
System.out.println("Path: " + file.getPath());
System.out.println("Parent: " + file.getParent());
System.out.println("Exists: " + file.exists());
System.out.println("Is file: " + file.isFile());
System.out.println("Is directory: " + file.isDirectory());
System.out.println("Is hidden: " + file.isHidden());
System.out.println("Can read: " + file.canRead());
System.out.println("Can write: " + file.canWrite());
System.out.println("Can execute: " + file.canExecute());
System.out.println("Length: " + file.length() + " bytes");
System.out.println("Last modified: " + new Date(file.lastModified()));
// File operations
System.out.println("\n=== File Operations ===");
try {
if (file.createNewFile()) {
System.out.println("File created: " + file.getName());
} else {
System.out.println("File already exists.");
}
// Rename file
File newFile = new File("renamed_example.txt");
if (file.renameTo(newFile)) {
System.out.println("File renamed to: " + newFile.getName());
file = newFile; // Update reference
}
// Delete file
if (file.delete()) {
System.out.println("File deleted: " + file.getName());
}
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Directory operations
System.out.println("\n=== Directory Operations ===");
if (directory.mkdir()) {
System.out.println("Directory created: " + directory.getName());
}
// List directory contents
File currentDir = new File(".");
System.out.println("\nContents of current directory:");
String[] files = currentDir.list();
if (files != null) {
for (String f : files) {
System.out.println(" " + f);
}
}
// Create temporary file
System.out.println("\n=== Temporary File ===");
try {
File tempFile = File.createTempFile("temp", ".txt");
System.out.println("Temp file created: " + tempFile.getAbsolutePath());
tempFile.deleteOnExit(); // Delete on JVM exit
} catch (IOException e) {
e.printStackTrace();
}
}
}
| Method | Description | Return Type |
|---|---|---|
boolean exists() |
Checks if file/directory exists | boolean |
boolean createNewFile() |
Creates new empty file | boolean |
boolean delete() |
Deletes file/directory | boolean |
boolean mkdir() |
Creates directory | boolean |
boolean renameTo(File dest) |
Renames file/directory | boolean |
long length() |
Returns file size in bytes | long |
String[] list() |
Lists files in directory | String[] |
boolean isFile() |
Checks if it's a file | boolean |
boolean isDirectory() |
Checks if it's a directory | boolean |
long lastModified() |
Returns last modified timestamp | long |
- Always check
exists()before operations - Use
getAbsolutePath()for full paths - Handle
SecurityExceptionfor permission issues - Use
deleteOnExit()for temporary files - Check return values of file operations
- Prefer
PathsandFilesclasses (Java NIO) for new code
3. FileReader and FileWriter Classes
FileReader and FileWriter are character streams used for reading and writing text files. They work with characters (16-bit Unicode) rather than bytes.
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterExample {
public static void main(String[] args) {
// FileWriter with automatic resource management (try-with-resources)
try (FileWriter writer = new FileWriter("output.txt")) {
// Write different types of data
writer.write("Hello, FileWriter!\n");
writer.write("This is a text file created using Java.\n");
writer.write("Current timestamp: " + System.currentTimeMillis() + "\n");
// Write character array
char[] chars = {'A', 'B', 'C', 'D', 'E', '\n'};
writer.write(chars);
// Write portion of character array
writer.write(chars, 1, 3); // Writes 'B', 'C', 'D'
writer.write('\n');
// Append mode
try (FileWriter appendWriter = new FileWriter("output.txt", true)) {
appendWriter.write("\n--- Appended Content ---\n");
appendWriter.write("This line was appended to the file.\n");
}
System.out.println("File written successfully!");
} catch (IOException e) {
System.out.println("Error writing file: " + e.getMessage());
}
// Writing with manual exception handling
System.out.println("\n=== Manual File Writing ===");
FileWriter manualWriter = null;
try {
manualWriter = new FileWriter("manual_output.txt");
manualWriter.write("Manual file writing example.\n");
manualWriter.write("Line 2\n");
manualWriter.write("Line 3\n");
System.out.println("Manual file written successfully!");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
} finally {
try {
if (manualWriter != null) {
manualWriter.close();
}
} catch (IOException e) {
System.out.println("Error closing writer: " + e.getMessage());
}
}
}
}
import java.io.FileReader;
import java.io.IOException;
public class FileReaderExample {
public static void main(String[] args) {
System.out.println("=== Reading File Character by Character ===");
try (FileReader reader = new FileReader("output.txt")) {
int charCode;
int charCount = 0;
System.out.println("File content:");
System.out.println("-------------");
// Read character by character
while ((charCode = reader.read()) != -1) {
char character = (char) charCode;
System.out.print(character);
charCount++;
}
System.out.println("\n-------------");
System.out.println("Total characters read: " + charCount);
} catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
}
System.out.println("\n=== Reading File into Character Array ===");
try (FileReader reader = new FileReader("output.txt")) {
char[] buffer = new char[1024];
int charsRead;
StringBuilder content = new StringBuilder();
// Read into character array buffer
while ((charsRead = reader.read(buffer)) != -1) {
content.append(buffer, 0, charsRead);
}
System.out.println("File content (using buffer):");
System.out.println(content.toString());
// Get file statistics
String fileContent = content.toString();
System.out.println("\nFile Statistics:");
System.out.println("Total characters: " + fileContent.length());
System.out.println("Total lines: " + (fileContent.split("\n").length));
System.out.println("Total words: " + fileContent.split("\\s+").length);
} catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
}
System.out.println("\n=== Reading with Manual Exception Handling ===");
FileReader manualReader = null;
try {
manualReader = new FileReader("manual_output.txt");
char[] smallBuffer = new char[100];
int count = manualReader.read(smallBuffer);
if (count != -1) {
System.out.println("First 100 characters:");
System.out.println(new String(smallBuffer, 0, count));
}
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
} finally {
try {
if (manualReader != null) {
manualReader.close();
}
} catch (IOException e) {
System.out.println("Error closing reader: " + e.getMessage());
}
}
}
}
| Class | Constructor | Key Methods | Use Case |
|---|---|---|---|
FileWriter |
FileWriter(String fileName)FileWriter(String fileName, boolean append) |
write(int c)write(String str)write(char[] cbuf)flush()close() |
Writing text files, simple logging |
FileReader |
FileReader(String fileName) |
read()read(char[] cbuf)skip(long n)close() |
Reading text files, configuration files |
FileReaderuses platform's default charset - may cause encoding issues- Always close streams in finally block or use try-with-resources
FileWritermay create file if it doesn't exist- For better performance, use buffered streams
- Consider
InputStreamReaderandOutputStreamWriterfor specific charsets
4. BufferedReader and BufferedWriter
BufferedReader and BufferedWriter add buffering capability to character streams, significantly improving I/O performance by reducing the number of physical read/write operations.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class BufferedRWExample {
public static void main(String[] args) {
// Writing with BufferedWriter
System.out.println("=== Writing with BufferedWriter ===");
try (BufferedWriter writer = new BufferedWriter(new FileWriter("buffered_output.txt"))) {
// Write lines efficiently
writer.write("=== Student Records ===\n");
writer.newLine(); // Platform-independent newline
for (int i = 1; i <= 5; i++) {
String record = String.format("Student %d: Score = %d, Grade = %c",
i, 75 + i * 5, (char)('A' + i % 3));
writer.write(record);
writer.newLine();
}
writer.write("=== End of Records ===");
writer.flush(); // Ensure all data is written
System.out.println("File written successfully with BufferedWriter");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Reading with BufferedReader
System.out.println("\n=== Reading with BufferedReader ===");
try (BufferedReader reader = new BufferedReader(new FileReader("buffered_output.txt"))) {
System.out.println("File content (line by line):");
System.out.println("-----------------------------");
String line;
int lineNumber = 1;
// Read line by line - most common pattern
while ((line = reader.readLine()) != null) {
System.out.printf("%3d: %s\n", lineNumber++, line);
}
System.out.println("-----------------------------");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Advanced BufferedReader features
System.out.println("\n=== Advanced BufferedReader Operations ===");
try (BufferedReader reader = new BufferedReader(new FileReader("buffered_output.txt"))) {
// Mark and reset example
reader.mark(100); // Mark current position
System.out.println("First 2 lines:");
for (int i = 0; i < 2; i++) {
System.out.println(reader.readLine());
}
reader.reset(); // Go back to marked position
System.out.println("\nAfter reset - First 2 lines again:");
for (int i = 0; i < 2; i++) {
System.out.println(reader.readLine());
}
// Skip characters
reader.skip(10);
System.out.println("\nAfter skipping 10 characters:");
System.out.println(reader.readLine());
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Practical example: Read all lines into List
System.out.println("\n=== Read All Lines into List ===");
List lines = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader("buffered_output.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
System.out.println("Total lines read: " + lines.size());
System.out.println("Lines containing 'Student':");
lines.stream()
.filter(l -> l.contains("Student"))
.forEach(System.out::println);
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Copy file with buffered streams
System.out.println("\n=== Copy File (Buffered) ===");
try (BufferedReader source = new BufferedReader(new FileReader("buffered_output.txt"));
BufferedWriter destination = new BufferedWriter(new FileWriter("copy_output.txt"))) {
String line;
int lineCount = 0;
while ((line = source.readLine()) != null) {
destination.write(line);
destination.newLine();
lineCount++;
}
System.out.println("File copied successfully!");
System.out.println("Lines copied: " + lineCount);
} catch (IOException e) {
System.out.println("Error copying file: " + e.getMessage());
}
}
}
Advantages of Buffered Streams
- Performance: Reduces physical I/O operations
- Line-oriented:
readLine()andnewLine()methods - Mark/Reset: Supports mark/reset operations
- Efficiency: Better for large files
- Flexibility: Can wrap any Reader/Writer
- Standard: Default buffer size (8192 chars) works well
Key Methods
readLine()- Reads entire line (BufferedReader)newLine()- Writes line separator (BufferedWriter)mark(int)- Marks current positionreset()- Returns to marked positionskip(long)- Skips charactersflush()- Forces buffer write
| BufferedReader Methods | Description | BufferedWriter Methods | Description |
|---|---|---|---|
String readLine() |
Reads a line of text | void newLine() |
Writes line separator |
boolean ready() |
Checks if stream is ready to read | void flush() |
Flushes the stream |
void mark(int) |
Marks current position | void write(String) |
Writes a string |
void reset() |
Resets to marked position | void write(char[]) |
Writes character array |
long skip(long) |
Skips characters | void write(String, int, int) |
Writes portion of string |
5. FileInputStream and FileOutputStream
FileInputStream and FileOutputStream are byte streams used for reading and writing binary data like images, audio, video, or any raw byte data.
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamExample {
public static void main(String[] args) {
// Writing bytes to file
System.out.println("=== Writing Bytes with FileOutputStream ===");
try (FileOutputStream fos = new FileOutputStream("binary_data.dat")) {
// Write single bytes
fos.write(65); // ASCII 'A'
fos.write(66); // ASCII 'B'
fos.write(67); // ASCII 'C'
fos.write(10); // Newline
// Write byte array
byte[] data = {68, 69, 70, 71, 72, 10}; // DEFGH + newline
fos.write(data);
// Write portion of byte array
byte[] fullData = "Hello Binary World!\n".getBytes();
fos.write(fullData);
// Write numbers as bytes
for (int i = 0; i <= 255; i++) {
fos.write(i);
}
System.out.println("Binary file created successfully!");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Append mode
System.out.println("\n=== Appending Bytes ===");
try (FileOutputStream fos = new FileOutputStream("binary_data.dat", true)) {
fos.write("\n=== Appended Data ===\n".getBytes());
fos.write("This was appended to the binary file.\n".getBytes());
System.out.println("Data appended successfully!");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
// Writing different data types
System.out.println("\n=== Writing Various Data Types ===");
try (FileOutputStream fos = new FileOutputStream("mixed_data.dat")) {
// Write string
String text = "Text data\n";
fos.write(text.getBytes());
// Write integer (4 bytes)
int number = 123456;
fos.write((number >> 24) & 0xFF);
fos.write((number >> 16) & 0xFF);
fos.write((number >> 8) & 0xFF);
fos.write(number & 0xFF);
fos.write('\n');
// Write double (8 bytes)
double value = 3.14159;
long doubleBits = Double.doubleToLongBits(value);
for (int i = 56; i >= 0; i -= 8) {
fos.write((int)((doubleBits >> i) & 0xFF));
}
fos.write('\n');
System.out.println("Mixed data file created!");
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamExample {
public static void main(String[] args) {
System.out.println("=== Reading Bytes with FileInputStream ===");
try (FileInputStream fis = new FileInputStream("binary_data.dat")) {
System.out.println("Available bytes: " + fis.available());
System.out.println("File content as bytes:");
System.out.println("----------------------");
// Read byte by byte
int byteValue;
int byteCount = 0;
while ((byteValue = fis.read()) != -1) {
if (byteCount % 16 == 0) {
System.out.println();
System.out.printf("%04X: ", byteCount);
}
System.out.printf("%02X ", byteValue);
byteCount++;
// Show ASCII representation for printable characters
if (byteCount % 16 == 0) {
System.out.print(" ");
// To show ASCII, we'd need to buffer the last 16 bytes
}
}
System.out.println("\n----------------------");
System.out.println("Total bytes read: " + byteCount);
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
System.out.println("\n=== Reading into Byte Array ===");
try (FileInputStream fis = new FileInputStream("binary_data.dat")) {
byte[] buffer = new byte[1024];
int bytesRead;
int totalBytes = 0;
while ((bytesRead = fis.read(buffer)) != -1) {
totalBytes += bytesRead;
// Process first 100 bytes as ASCII
if (totalBytes <= 100) {
System.out.println("First " + bytesRead + " bytes as text:");
for (int i = 0; i < bytesRead; i++) {
char c = (char) buffer[i];
if (c >= 32 && c <= 126) { // Printable ASCII
System.out.print(c);
} else if (c == 10 || c == 13) {
System.out.print("\\n");
} else {
System.out.print('.');
}
}
System.out.println();
}
}
System.out.println("Total bytes read (buffered): " + totalBytes);
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
System.out.println("\n=== File Copy using Byte Streams ===");
try (FileInputStream source = new FileInputStream("binary_data.dat");
FileOutputStream destination = new FileOutputStream("copy_binary.dat")) {
byte[] buffer = new byte[4096]; // 4KB buffer
int bytesRead;
long totalCopied = 0;
long startTime = System.currentTimeMillis();
while ((bytesRead = source.read(buffer)) != -1) {
destination.write(buffer, 0, bytesRead);
totalCopied += bytesRead;
}
long endTime = System.currentTimeMillis();
System.out.println("File copied successfully!");
System.out.println("Bytes copied: " + totalCopied);
System.out.println("Time taken: " + (endTime - startTime) + " ms");
} catch (IOException e) {
System.out.println("Error copying file: " + e.getMessage());
}
// Reading with skip and available
System.out.println("\n=== Using skip() and available() ===");
try (FileInputStream fis = new FileInputStream("binary_data.dat")) {
System.out.println("Initially available: " + fis.available() + " bytes");
// Skip first 10 bytes
long skipped = fis.skip(10);
System.out.println("Skipped " + skipped + " bytes");
System.out.println("Now available: " + fis.available() + " bytes");
// Read next 5 bytes
byte[] smallBuffer = new byte[5];
int read = fis.read(smallBuffer);
System.out.println("Read " + read + " bytes after skipping:");
for (int i = 0; i < read; i++) {
System.out.printf("%02X ", smallBuffer[i]);
}
System.out.println();
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
| Class | Key Methods | Description | Use Cases |
|---|---|---|---|
FileInputStream |
read()read(byte[] b)available()skip(long n)close() |
Reads raw bytes from files | Images, audio, video, binary files |
FileOutputStream |
write(int b)write(byte[] b)flush()close() |
Writes raw bytes to files | Binary file creation, data logging |
- Byte Streams (InputStream/OutputStream): Handle raw binary data, platform-independent
- Character Streams (Reader/Writer): Handle text data, handle character encoding
- Use Byte Streams for: Images, audio, video, executable files
- Use Character Streams for: Text files, configuration files, CSV, JSON
- Performance: Byte streams are faster for binary data
- Buffering: Always use buffered versions for better performance
6. Java File Handling Built-in Functions Reference
Complete reference of all important methods and constructors available in Java File Handling classes.
File Class Methods
| Method Signature | Description | Return Type |
|---|---|---|
boolean exists() |
Tests whether file/directory exists | boolean |
boolean createNewFile() |
Atomically creates new empty file | boolean |
boolean delete() |
Deletes file/directory | boolean |
boolean mkdir() |
Creates directory | boolean |
boolean mkdirs() |
Creates directory including parents | boolean |
boolean renameTo(File dest) |
Renames file/directory | boolean |
long length() |
Returns file size in bytes | long |
String getName() |
Returns file/directory name | String |
String getPath() |
Returns path string | String |
String getAbsolutePath() |
Returns absolute path string | String |
String getParent() |
Returns parent directory path | String |
boolean isFile() |
Tests if it's a normal file | boolean |
boolean isDirectory() |
Tests if it's a directory | boolean |
boolean isHidden() |
Tests if file is hidden | boolean |
boolean canRead() |
Tests if application can read | boolean |
boolean canWrite() |
Tests if application can write | boolean |
boolean canExecute() |
Tests if application can execute | boolean |
long lastModified() |
Returns last modified timestamp | long |
String[] list() |
Lists files in directory | String[] |
File[] listFiles() |
Lists files as File objects | File[] |
static File[] listRoots() |
Lists available filesystem roots | File[] |
boolean setReadOnly() |
Marks file/directory read-only | boolean |
boolean setWritable(boolean) |
Sets write permission | boolean |
boolean setReadable(boolean) |
Sets read permission | boolean |
boolean setExecutable(boolean) |
Sets execute permission | boolean |
FileReader and FileWriter Constructors
| Constructor | Description | Throws |
|---|---|---|
FileReader(String fileName) |
Creates FileReader from file name | FileNotFoundException |
FileReader(File file) |
Creates FileReader from File object | FileNotFoundException |
FileReader(FileDescriptor fd) |
Creates FileReader from FileDescriptor | - |
FileWriter(String fileName) |
Creates FileWriter from file name | IOException |
FileWriter(String fileName, boolean append) |
Creates FileWriter with append mode | IOException |
FileWriter(File file) |
Creates FileWriter from File object | IOException |
FileWriter(File file, boolean append) |
Creates FileWriter with append mode | IOException |
FileWriter(FileDescriptor fd) |
Creates FileWriter from FileDescriptor | - |
BufferedReader and BufferedWriter Methods
| Class | Method | Description | Return Type |
|---|---|---|---|
BufferedReader |
String readLine() |
Reads a line of text | String |
boolean ready() |
Checks if stream is ready to read | boolean | |
void mark(int readAheadLimit) |
Marks current position | void | |
void reset() |
Resets stream to marked position | void | |
long skip(long n) |
Skips characters | long | |
Stream<String> lines() |
Returns Stream of lines (Java 8+) | Stream<String> | |
BufferedWriter |
void newLine() |
Writes line separator | void |
void write(String s, int off, int len) |
Writes portion of string | void | |
void flush() |
Flushes the stream | void |
FileInputStream and FileOutputStream Methods
| Class | Method | Description | Return Type |
|---|---|---|---|
FileInputStream |
int read() |
Reads byte of data | int |
int read(byte[] b) |
Reads bytes into array | int | |
int read(byte[] b, int off, int len) |
Reads bytes into portion of array | int | |
long skip(long n) |
Skips bytes | long | |
int available() |
Returns available bytes | int | |
FileOutputStream |
void write(int b) |
Writes byte of data | void |
void write(byte[] b) |
Writes byte array | void | |
void write(byte[] b, int off, int len) |
Writes portion of byte array | void | |
FileChannel getChannel() |
Returns FileChannel object | FileChannel |
Key Points to Remember
- Always close streams in finally block or use try-with-resources
- Use buffered streams for better performance
- Check file existence before operations
- Handle exceptions appropriately
- Use character streams for text, byte streams for binary data
- Consider Java NIO (Files, Paths) for new code
7. Practical File Handling Examples
Example 1: CSV File Processor
import java.io.*;
import java.util.*;
public class CSVFileProcessor {
public static void writeCSV(String filename, List data) throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
for (String[] row : data) {
writer.write(String.join(",", row));
writer.newLine();
}
}
System.out.println("CSV file created: " + filename);
}
public static List readCSV(String filename) throws IOException {
List data = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = reader.readLine()) != null) {
String[] row = line.split(",");
data.add(row);
}
}
return data;
}
public static void main(String[] args) {
// Sample data
List employeeData = Arrays.asList(
new String[]{"ID", "Name", "Department", "Salary"},
new String[]{"1", "John Doe", "Engineering", "75000"},
new String[]{"2", "Jane Smith", "Marketing", "65000"},
new String[]{"3", "Bob Johnson", "Sales", "70000"},
new String[]{"4", "Alice Brown", "HR", "60000"}
);
try {
// Write CSV file
writeCSV("employees.csv", employeeData);
// Read and process CSV
List readData = readCSV("employees.csv");
System.out.println("\n=== Employee Report ===");
double totalSalary = 0;
int dataRows = 0;
for (int i = 0; i < readData.size(); i++) {
String[] row = readData.get(i);
if (i == 0) {
// Header
System.out.printf("%-5s %-15s %-15s %10s\n",
row[0], row[1], row[2], row[3]);
System.out.println("------------------------------------------------");
} else {
// Data rows
System.out.printf("%-5s %-15s %-15s %10s\n",
row[0], row[1], row[2], row[3]);
if (row.length >= 4) {
try {
totalSalary += Double.parseDouble(row[3]);
dataRows++;
} catch (NumberFormatException e) {
System.out.println("Warning: Invalid salary format for row " + i);
}
}
}
}
System.out.println("------------------------------------------------");
System.out.printf("Total Employees: %d\n", dataRows);
System.out.printf("Total Salary: $%.2f\n", totalSalary);
System.out.printf("Average Salary: $%.2f\n", totalSalary / dataRows);
// Update CSV (add bonus)
System.out.println("\n=== Adding 10% Bonus ===");
List updatedData = new ArrayList<>();
updatedData.add(readData.get(0)); // Header
for (int i = 1; i < readData.size(); i++) {
String[] row = readData.get(i);
if (row.length >= 4) {
try {
double salary = Double.parseDouble(row[3]);
double bonus = salary * 0.10;
String[] newRow = Arrays.copyOf(row, row.length + 1);
newRow[newRow.length - 1] = String.format("%.2f", bonus);
updatedData.add(newRow);
} catch (NumberFormatException e) {
updatedData.add(row);
}
}
}
// Update header
updatedData.get(0) = new String[]{"ID", "Name", "Department", "Salary", "Bonus"};
writeCSV("employees_with_bonus.csv", updatedData);
System.out.println("Updated CSV file created with bonus column!");
} catch (IOException e) {
System.out.println("Error processing CSV: " + e.getMessage());
}
}
}
Example 2: Configuration File Manager
import java.io.*;
import java.util.*;
public class ConfigFileManager {
private String configFile;
private Properties properties;
public ConfigFileManager(String configFile) {
this.configFile = configFile;
this.properties = new Properties();
}
public void loadConfig() throws IOException {
try (FileInputStream fis = new FileInputStream(configFile)) {
properties.load(fis);
System.out.println("Configuration loaded from: " + configFile);
}
}
public void saveConfig() throws IOException {
try (FileOutputStream fos = new FileOutputStream(configFile)) {
properties.store(fos, "Application Configuration");
System.out.println("Configuration saved to: " + configFile);
}
}
public String getProperty(String key) {
return properties.getProperty(key);
}
public void setProperty(String key, String value) {
properties.setProperty(key, value);
}
public void displayAllProperties() {
System.out.println("\n=== Current Configuration ===");
properties.forEach((key, value) ->
System.out.printf("%-30s = %s\n", key, value));
}
public static void main(String[] args) {
ConfigFileManager configManager = new ConfigFileManager("app_config.properties");
try {
// Check if config file exists
File configFile = new File("app_config.properties");
if (!configFile.exists()) {
System.out.println("Config file not found. Creating default configuration...");
// Set default properties
configManager.setProperty("app.name", "MyApplication");
configManager.setProperty("app.version", "1.0.0");
configManager.setProperty("database.url", "jdbc:mysql://localhost:3306/mydb");
configManager.setProperty("database.username", "admin");
configManager.setProperty("database.password", "secret123");
configManager.setProperty("server.port", "8080");
configManager.setProperty("log.level", "INFO");
configManager.setProperty("cache.enabled", "true");
configManager.setProperty("max.connections", "100");
configManager.setProperty("timeout.seconds", "30");
// Save default config
configManager.saveConfig();
}
// Load existing config
configManager.loadConfig();
configManager.displayAllProperties();
// Update some properties
System.out.println("\n=== Updating Configuration ===");
configManager.setProperty("log.level", "DEBUG");
configManager.setProperty("timeout.seconds", "60");
// Add new property
configManager.setProperty("feature.new", "enabled");
// Save updated config
configManager.saveConfig();
// Display updated config
configManager.loadConfig();
configManager.displayAllProperties();
// Search for specific properties
System.out.println("\n=== Database Configuration ===");
propertiesStartingWith(configManager.properties, "database")
.forEach((k, v) -> System.out.println(k + " = " + v));
System.out.println("\n=== Application Info ===");
propertiesStartingWith(configManager.properties, "app")
.forEach((k, v) -> System.out.println(k + " = " + v));
// Backup configuration
backupConfig("app_config.properties",
"app_config_backup_" + System.currentTimeMillis() + ".properties");
} catch (IOException e) {
System.out.println("Error managing configuration: " + e.getMessage());
}
}
private static Map propertiesStartingWith(Properties props, String prefix) {
Map result = new TreeMap<>();
props.forEach((keyObj, valueObj) -> {
String key = (String) keyObj;
if (key.startsWith(prefix + ".")) {
result.put(key, (String) valueObj);
}
});
return result;
}
private static void backupConfig(String sourceFile, String backupFile) throws IOException {
try (FileInputStream fis = new FileInputStream(sourceFile);
FileOutputStream fos = new FileOutputStream(backupFile)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
System.out.println("\nConfiguration backed up to: " + backupFile);
}
}
}
8. File Handling Best Practices
- Not closing streams: Causes resource leaks
- Ignoring exceptions: Empty catch blocks
- Hardcoded file paths: Platform dependency
- No file existence checks: FileNotFoundException
- Large file memory loading: OutOfMemoryError
- No buffering: Poor performance
- Wrong stream type: Using byte stream for text
File Handling Best Practices
- Always use try-with-resources (Java 7+)
- Use buffered streams for better performance
- Check file existence before operations
- Handle all I/O exceptions appropriately
- Use relative paths or configuration
- Close streams in finally block if not using try-with-resources
- Use character streams for text, byte streams for binary
Performance Tips
- Use appropriate buffer size (4KB-8KB)
- Process large files in chunks
- Avoid reading entire file into memory
- Use NIO for high-performance I/O
- Consider memory-mapped files for random access
- Use asynchronous I/O for concurrent operations
Choosing the Right File Handling Approach
For text files: BufferedReader/BufferedWriter
For binary files: BufferedInputStream/BufferedOutputStream
For configuration: Properties class with FileInputStream/FileOutputStream
For large files: Process in chunks, use NIO
For temporary files: File.createTempFile() with deleteOnExit()
New projects: Prefer java.nio.file.Files and Paths
For new Java applications, consider using the java.nio package (Files, Paths, FileChannel) which offers:
- Better performance with buffers and channels
- Non-blocking I/O operations
- File system abstraction
- Atomic operations
- Better exception handling
Example: Files.readAllLines(Paths.get("file.txt"))