4.7 Java File I/O Operations
4.7 Java File I/O Operations
File input/output operations are essential for most Java applications. Java provides multiple approaches for file handling, from traditional streams to modern NIO.2 APIs. Understanding these different approaches helps you choose the right tool for each situation.
Prerequisites: This guide assumes familiarity with Java exception handling, streams, and basic OOP concepts. Review Collections Framework for understanding data structures used in examples.
File I/O Evolution in Java
Java has evolved its file handling capabilities over time:
- Java 1.0: Basic
FileInputStream/FileOutputStream - Java 1.1: Character streams with
FileReader/FileWriter - Java 1.4: NIO (New I/O) with channels and buffers
- Java 7: NIO.2 with
PathandFilesclasses - Java 8+: Stream API integration
Basic File Operations with Traditional I/O
Reading Files with Character Streams
1import java.io.*;
2import java.util.*;
3
4public class TraditionalFileReading {
5
6 public static void readFileWithBufferedReader(String filename) {
7 System.out.println("=== Reading with BufferedReader ===");
8
9 try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
10 String line;
11 int lineNumber = 1;
12
13 while ((line = reader.readLine()) != null) {
14 System.out.println(lineNumber + ": " + line);
15 lineNumber++;
16 }
17
18 } catch (FileNotFoundException e) {
19 System.err.println("File not found: " + filename);
20 } catch (IOException e) {
21 System.err.println("Error reading file: " + e.getMessage());
22 }
23 }
24
25 public static void readFileCharByChar(String filename) {
26 System.out.println("\n=== Reading Character by Character ===");
27
28 try (FileReader reader = new FileReader(filename)) {
29 int character;
30 int charCount = 0;
31
32 while ((character = reader.read()) != -1) {
33 char ch = (char) character;
34 System.out.print(ch);
35 charCount++;
36
37 // Show progress every 100 characters
38 if (charCount % 100 == 0) {
39 System.out.println("\n[" + charCount + " characters read]");
40 }
41 }
42
43 System.out.println("\nTotal characters read: " + charCount);
44
45 } catch (IOException e) {
46 System.err.println("Error reading file: " + e.getMessage());
47 }
48 }
49
50 public static List<String> readFileToList(String filename) {
51 System.out.println("\n=== Reading File to List ===");
52
53 List<String> lines = new ArrayList<>();
54
55 try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
56 String line;
57
58 while ((line = reader.readLine()) != null) {
59 lines.add(line);
60 }
61
62 System.out.println("Read " + lines.size() + " lines from file");
63
64 } catch (IOException e) {
65 System.err.println("Error reading file: " + e.getMessage());
66 }
67
68 return lines;
69 }
70
71 public static void demonstrateReading() {
72 String filename = "sample.txt";
73
74 // Create a sample file first
75 createSampleFile(filename);
76
77 // Demonstrate different reading methods
78 readFileWithBufferedReader(filename);
79 readFileToList(filename);
80 }
81
82 private static void createSampleFile(String filename) {
83 try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
84 writer.println("This is line 1");
85 writer.println("This is line 2 with some longer content");
86 writer.println("Line 3 contains numbers: 123, 456, 789");
87 writer.println("Line 4 has special characters: @#$%^&*()");
88 writer.println("Final line with mixed content: Hello World! 2024");
89 } catch (IOException e) {
90 System.err.println("Error creating sample file: " + e.getMessage());
91 }
92 }
93}Writing Files with Character Streams
1import java.io.*;
2import java.util.*;
3import java.time.LocalDateTime;
4import java.time.format.DateTimeFormatter;
5
6public class TraditionalFileWriting {
7
8 public static void writeWithPrintWriter(String filename, List<String> data) {
9 System.out.println("=== Writing with PrintWriter ===");
10
11 try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
12
13 // Write header with timestamp
14 writer.println("# File generated on: " + LocalDateTime.now());
15 writer.println("# Total entries: " + data.size());
16 writer.println("=" * 40);
17
18 // Write data with line numbers
19 for (int i = 0; i < data.size(); i++) {
20 writer.printf("%d: %s%n", i + 1, data.get(i));
21 }
22
23 writer.println("=" * 40);
24 writer.println("# End of file");
25
26 System.out.println("Successfully wrote " + data.size() + " entries to " + filename);
27
28 } catch (IOException e) {
29 System.err.println("Error writing file: " + e.getMessage());
30 }
31 }
32
33 public static void appendToFile(String filename, String content) {
34 System.out.println("\n=== Appending to File ===");
35
36 try (PrintWriter writer = new PrintWriter(new FileWriter(filename, true))) {
37 writer.println();
38 writer.println("# Appended on: " + LocalDateTime.now());
39 writer.println(content);
40
41 System.out.println("Successfully appended content to " + filename);
42
43 } catch (IOException e) {
44 System.err.println("Error appending to file: " + e.getMessage());
45 }
46 }
47
48 public static void writeFormattedData(String filename) {
49 System.out.println("\n=== Writing Formatted Data ===");
50
51 // Sample data
52 List<Student> students = Arrays.asList(
53 new Student("Alice Johnson", 123, 3.85),
54 new Student("Bob Smith", 456, 3.92),
55 new Student("Charlie Brown", 789, 3.67),
56 new Student("Diana Prince", 321, 3.99)
57 );
58
59 try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
60
61 // Write CSV header
62 writer.println("Name,ID,GPA");
63
64 // Write student data
65 for (Student student : students) {
66 writer.printf("%s,%d,%.2f%n",
67 student.getName(),
68 student.getId(),
69 student.getGpa()
70 );
71 }
72
73 System.out.println("Successfully wrote " + students.size() + " students to CSV file");
74
75 } catch (IOException e) {
76 System.err.println("Error writing CSV file: " + e.getMessage());
77 }
78 }
79
80 public static void writeWithBufferedWriter(String filename, List<String> lines) {
81 System.out.println("\n=== Writing with BufferedWriter ===");
82
83 try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
84
85 for (String line : lines) {
86 writer.write(line);
87 writer.newLine(); // Platform-independent line separator
88 }
89
90 // Explicitly flush to ensure data is written
91 writer.flush();
92
93 System.out.println("Successfully wrote " + lines.size() + " lines using BufferedWriter");
94
95 } catch (IOException e) {
96 System.err.println("Error writing with BufferedWriter: " + e.getMessage());
97 }
98 }
99
100 // Helper class for formatted data example
101 static class Student {
102 private String name;
103 private int id;
104 private double gpa;
105
106 public Student(String name, int id, double gpa) {
107 this.name = name;
108 this.id = id;
109 this.gpa = gpa;
110 }
111
112 public String getName() { return name; }
113 public int getId() { return id; }
114 public double getGpa() { return gpa; }
115 }
116
117 public static void demonstrateWriting() {
118 List<String> sampleData = Arrays.asList(
119 "First line of data",
120 "Second line with more content",
121 "Third line containing special chars: !@#$%",
122 "Fourth line with numbers: 12345",
123 "Last line of the sample data"
124 );
125
126 writeWithPrintWriter("output1.txt", sampleData);
127 appendToFile("output1.txt", "This content was appended later");
128 writeFormattedData("students.csv");
129 writeWithBufferedWriter("output2.txt", sampleData);
130 }
131}Binary File Operations
Reading and Writing Binary Data
1import java.io.*;
2import java.util.Arrays;
3
4public class BinaryFileOperations {
5
6 public static void writeBinaryData(String filename) {
7 System.out.println("=== Writing Binary Data ===");
8
9 try (DataOutputStream dos = new DataOutputStream(
10 new BufferedOutputStream(new FileOutputStream(filename)))) {
11
12 // Write different data types
13 dos.writeInt(42); // 4 bytes
14 dos.writeDouble(3.14159); // 8 bytes
15 dos.writeBoolean(true); // 1 byte
16 dos.writeUTF("Hello, Binary!"); // Variable length string
17 dos.writeLong(1234567890L); // 8 bytes
18 dos.writeFloat(2.718f); // 4 bytes
19
20 // Write an array
21 int[] numbers = {1, 2, 3, 4, 5};
22 dos.writeInt(numbers.length); // Array length first
23 for (int num : numbers) {
24 dos.writeInt(num);
25 }
26
27 System.out.println("Binary data written successfully");
28
29 } catch (IOException e) {
30 System.err.println("Error writing binary data: " + e.getMessage());
31 }
32 }
33
34 public static void readBinaryData(String filename) {
35 System.out.println("\n=== Reading Binary Data ===");
36
37 try (DataInputStream dis = new DataInputStream(
38 new BufferedInputStream(new FileInputStream(filename)))) {
39
40 // Read data in the same order it was written
41 int intValue = dis.readInt();
42 double doubleValue = dis.readDouble();
43 boolean boolValue = dis.readBoolean();
44 String stringValue = dis.readUTF();
45 long longValue = dis.readLong();
46 float floatValue = dis.readFloat();
47
48 // Read the array
49 int arrayLength = dis.readInt();
50 int[] numbers = new int[arrayLength];
51 for (int i = 0; i < arrayLength; i++) {
52 numbers[i] = dis.readInt();
53 }
54
55 // Display the read data
56 System.out.println("Integer: " + intValue);
57 System.out.println("Double: " + doubleValue);
58 System.out.println("Boolean: " + boolValue);
59 System.out.println("String: " + stringValue);
60 System.out.println("Long: " + longValue);
61 System.out.println("Float: " + floatValue);
62 System.out.println("Array: " + Arrays.toString(numbers));
63
64 } catch (IOException e) {
65 System.err.println("Error reading binary data: " + e.getMessage());
66 }
67 }
68
69 public static void copyBinaryFile(String sourceFile, String targetFile) {
70 System.out.println("\n=== Copying Binary File ===");
71
72 try (InputStream input = new BufferedInputStream(new FileInputStream(sourceFile));
73 OutputStream output = new BufferedOutputStream(new FileOutputStream(targetFile))) {
74
75 byte[] buffer = new byte[8192]; // 8KB buffer
76 int bytesRead;
77 long totalBytes = 0;
78
79 while ((bytesRead = input.read(buffer)) != -1) {
80 output.write(buffer, 0, bytesRead);
81 totalBytes += bytesRead;
82 }
83
84 System.out.println("Copied " + totalBytes + " bytes from " + sourceFile + " to " + targetFile);
85
86 } catch (IOException e) {
87 System.err.println("Error copying file: " + e.getMessage());
88 }
89 }
90
91 public static void demonstrateSerialization() {
92 System.out.println("\n=== Object Serialization ===");
93
94 // Create a serializable object
95 SerializableStudent student = new SerializableStudent("John Doe", 12345, 3.75);
96 student.addGrade("Math", 95);
97 student.addGrade("Science", 88);
98 student.addGrade("English", 92);
99
100 String filename = "student.ser";
101
102 // Serialize the object
103 try (ObjectOutputStream oos = new ObjectOutputStream(
104 new FileOutputStream(filename))) {
105
106 oos.writeObject(student);
107 System.out.println("Student object serialized successfully");
108
109 } catch (IOException e) {
110 System.err.println("Error serializing object: " + e.getMessage());
111 }
112
113 // Deserialize the object
114 try (ObjectInputStream ois = new ObjectInputStream(
115 new FileInputStream(filename))) {
116
117 SerializableStudent deserializedStudent = (SerializableStudent) ois.readObject();
118 System.out.println("Deserialized student: " + deserializedStudent);
119
120 } catch (IOException | ClassNotFoundException e) {
121 System.err.println("Error deserializing object: " + e.getMessage());
122 }
123 }
124
125 // Serializable student class
126 static class SerializableStudent implements Serializable {
127 private static final long serialVersionUID = 1L;
128
129 private String name;
130 private int id;
131 private double gpa;
132 private Map<String, Integer> grades;
133
134 public SerializableStudent(String name, int id, double gpa) {
135 this.name = name;
136 this.id = id;
137 this.gpa = gpa;
138 this.grades = new HashMap<>();
139 }
140
141 public void addGrade(String subject, int grade) {
142 grades.put(subject, grade);
143 }
144
145 @Override
146 public String toString() {
147 return String.format("Student{name='%s', id=%d, gpa=%.2f, grades=%s}",
148 name, id, gpa, grades);
149 }
150 }
151
152 public static void demonstrateBinaryOperations() {
153 String binaryFile = "data.bin";
154
155 writeBinaryData(binaryFile);
156 readBinaryData(binaryFile);
157 copyBinaryFile(binaryFile, "data_copy.bin");
158 demonstrateSerialization();
159 }
160}Modern Java NIO.2 (Path and Files)
Working with Paths and Files
1import java.nio.file.*;
2import java.nio.charset.StandardCharsets;
3import java.io.IOException;
4import java.util.List;
5import java.util.stream.Stream;
6
7public class ModernFileOperations {
8
9 public static void demonstratePathOperations() {
10 System.out.println("=== Path Operations ===");
11
12 // Creating paths
13 Path currentDir = Paths.get(".");
14 Path absolutePath = currentDir.toAbsolutePath();
15 Path normalizedPath = absolutePath.normalize();
16
17 System.out.println("Current directory: " + currentDir);
18 System.out.println("Absolute path: " + absolutePath);
19 System.out.println("Normalized path: " + normalizedPath);
20
21 // Path components
22 Path filePath = Paths.get("/home/user/documents/file.txt");
23 System.out.println("\nPath analysis for: " + filePath);
24 System.out.println("Parent: " + filePath.getParent());
25 System.out.println("Filename: " + filePath.getFileName());
26 System.out.println("Root: " + filePath.getRoot());
27 System.out.println("Name count: " + filePath.getNameCount());
28
29 // Resolving paths
30 Path baseDir = Paths.get("/home/user");
31 Path resolvedPath = baseDir.resolve("documents/file.txt");
32 System.out.println("Resolved path: " + resolvedPath);
33
34 // Relativizing paths
35 Path path1 = Paths.get("/home/user/documents");
36 Path path2 = Paths.get("/home/user/pictures");
37 Path relativePath = path1.relativize(path2);
38 System.out.println("Relative path from documents to pictures: " + relativePath);
39 }
40
41 public static void readFileWithNIO(String filename) {
42 System.out.println("\n=== Reading with NIO.2 ===");
43
44 Path filePath = Paths.get(filename);
45
46 try {
47 // Read entire file as string
48 String content = Files.readString(filePath, StandardCharsets.UTF_8);
49 System.out.println("File content:\n" + content);
50
51 // Read all lines into a list
52 List<String> lines = Files.readAllLines(filePath, StandardCharsets.UTF_8);
53 System.out.println("\nFile has " + lines.size() + " lines");
54
55 // Read lines as a stream (memory efficient for large files)
56 System.out.println("\nProcessing lines with stream:");
57 try (Stream<String> lineStream = Files.lines(filePath)) {
58 lineStream
59 .filter(line -> line.contains("line"))
60 .map(String::toUpperCase)
61 .forEach(System.out::println);
62 }
63
64 } catch (IOException e) {
65 System.err.println("Error reading file: " + e.getMessage());
66 }
67 }
68
69 public static void writeFileWithNIO(String filename, List<String> data) {
70 System.out.println("\n=== Writing with NIO.2 ===");
71
72 Path filePath = Paths.get(filename);
73
74 try {
75 // Write all lines at once
76 Files.write(filePath, data, StandardCharsets.UTF_8);
77 System.out.println("Successfully wrote " + data.size() + " lines to " + filename);
78
79 // Append additional content
80 String additionalContent = "\nAppended with NIO.2";
81 Files.write(filePath, additionalContent.getBytes(StandardCharsets.UTF_8),
82 StandardOpenOption.APPEND);
83
84 System.out.println("Appended additional content");
85
86 } catch (IOException e) {
87 System.err.println("Error writing file: " + e.getMessage());
88 }
89 }
90
91 public static void fileMetadataOperations() {
92 System.out.println("\n=== File Metadata Operations ===");
93
94 Path filePath = Paths.get("sample.txt");
95
96 try {
97 // Check file existence and properties
98 boolean exists = Files.exists(filePath);
99 boolean isRegularFile = Files.isRegularFile(filePath);
100 boolean isDirectory = Files.isDirectory(filePath);
101 boolean isReadable = Files.isReadable(filePath);
102 boolean isWritable = Files.isWritable(filePath);
103 boolean isExecutable = Files.isExecutable(filePath);
104
105 System.out.println("File: " + filePath);
106 System.out.println("Exists: " + exists);
107 System.out.println("Is regular file: " + isRegularFile);
108 System.out.println("Is directory: " + isDirectory);
109 System.out.println("Is readable: " + isReadable);
110 System.out.println("Is writable: " + isWritable);
111 System.out.println("Is executable: " + isExecutable);
112
113 if (exists) {
114 // Get file attributes
115 long size = Files.size(filePath);
116 System.out.println("File size: " + size + " bytes");
117
118 // Get file times
119 BasicFileAttributes attrs = Files.readAttributes(filePath, BasicFileAttributes.class);
120 System.out.println("Creation time: " + attrs.creationTime());
121 System.out.println("Last modified: " + attrs.lastModifiedTime());
122 System.out.println("Last accessed: " + attrs.lastAccessTime());
123 }
124
125 } catch (IOException e) {
126 System.err.println("Error reading file metadata: " + e.getMessage());
127 }
128 }
129
130 public static void directoryOperations() {
131 System.out.println("\n=== Directory Operations ===");
132
133 Path currentDir = Paths.get(".");
134
135 try {
136 // List directory contents
137 System.out.println("Directory contents:");
138 try (Stream<Path> paths = Files.list(currentDir)) {
139 paths.filter(Files::isRegularFile)
140 .forEach(path -> {
141 try {
142 long size = Files.size(path);
143 System.out.println(path.getFileName() + " (" + size + " bytes)");
144 } catch (IOException e) {
145 System.out.println(path.getFileName() + " (size unknown)");
146 }
147 });
148 }
149
150 // Walk directory tree
151 System.out.println("\nWalking directory tree (max depth 2):");
152 try (Stream<Path> paths = Files.walk(currentDir, 2)) {
153 paths.filter(Files::isRegularFile)
154 .filter(path -> path.toString().endsWith(".txt"))
155 .forEach(System.out::println);
156 }
157
158 // Create directories
159 Path newDir = Paths.get("test_directory");
160 if (!Files.exists(newDir)) {
161 Files.createDirectory(newDir);
162 System.out.println("Created directory: " + newDir);
163
164 // Create a file in the new directory
165 Path newFile = newDir.resolve("test_file.txt");
166 Files.write(newFile, "This is a test file".getBytes());
167 System.out.println("Created file: " + newFile);
168 }
169
170 } catch (IOException e) {
171 System.err.println("Error in directory operations: " + e.getMessage());
172 }
173 }
174
175 public static void fileCopyMoveOperations() {
176 System.out.println("\n=== File Copy and Move Operations ===");
177
178 try {
179 // Create source file
180 Path sourceFile = Paths.get("source.txt");
181 Files.write(sourceFile, "This is the source file content".getBytes());
182
183 // Copy file
184 Path copyFile = Paths.get("copy.txt");
185 Files.copy(sourceFile, copyFile, StandardCopyOption.REPLACE_EXISTING);
186 System.out.println("Copied " + sourceFile + " to " + copyFile);
187
188 // Move file
189 Path movedFile = Paths.get("moved.txt");
190 Files.move(copyFile, movedFile, StandardCopyOption.REPLACE_EXISTING);
191 System.out.println("Moved " + copyFile + " to " + movedFile);
192
193 // Delete file
194 Files.delete(movedFile);
195 System.out.println("Deleted " + movedFile);
196
197 // Safe delete (doesn't throw exception if file doesn't exist)
198 boolean deleted = Files.deleteIfExists(sourceFile);
199 System.out.println("Source file deleted: " + deleted);
200
201 } catch (IOException e) {
202 System.err.println("Error in file operations: " + e.getMessage());
203 }
204 }
205
206 public static void demonstrateNIOOperations() {
207 // Create sample data
208 List<String> sampleData = Arrays.asList(
209 "Line 1: Introduction to NIO.2",
210 "Line 2: Path operations are powerful",
211 "Line 3: Files class provides many utilities",
212 "Line 4: Stream integration is excellent",
213 "Line 5: Modern Java file handling"
214 );
215
216 demonstratePathOperations();
217 writeFileWithNIO("nio_sample.txt", sampleData);
218 readFileWithNIO("nio_sample.txt");
219 fileMetadataOperations();
220 directoryOperations();
221 fileCopyMoveOperations();
222 }
223}Working with Different File Formats
CSV File Processing
1import java.io.*;
2import java.util.*;
3import java.util.stream.Collectors;
4
5public class CSVFileProcessor {
6
7 static class Employee {
8 private String name;
9 private String department;
10 private double salary;
11 private int experience;
12
13 public Employee(String name, String department, double salary, int experience) {
14 this.name = name;
15 this.department = department;
16 this.salary = salary;
17 this.experience = experience;
18 }
19
20 // Getters
21 public String getName() { return name; }
22 public String getDepartment() { return department; }
23 public double getSalary() { return salary; }
24 public int getExperience() { return experience; }
25
26 @Override
27 public String toString() {
28 return String.format("Employee{name='%s', dept='%s', salary=%.2f, exp=%d}",
29 name, department, salary, experience);
30 }
31
32 public String toCSV() {
33 return String.format("%s,%s,%.2f,%d", name, department, salary, experience);
34 }
35
36 public static Employee fromCSV(String csvLine) {
37 String[] parts = csvLine.split(",");
38 return new Employee(
39 parts[0].trim(),
40 parts[1].trim(),
41 Double.parseDouble(parts[2].trim()),
42 Integer.parseInt(parts[3].trim())
43 );
44 }
45 }
46
47 public static void writeEmployeesToCSV(String filename, List<Employee> employees) {
48 System.out.println("=== Writing Employees to CSV ===");
49
50 try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
51 // Write header
52 writer.println("Name,Department,Salary,Experience");
53
54 // Write employee data
55 for (Employee emp : employees) {
56 writer.println(emp.toCSV());
57 }
58
59 System.out.println("Successfully wrote " + employees.size() + " employees to " + filename);
60
61 } catch (IOException e) {
62 System.err.println("Error writing CSV file: " + e.getMessage());
63 }
64 }
65
66 public static List<Employee> readEmployeesFromCSV(String filename) {
67 System.out.println("\n=== Reading Employees from CSV ===");
68
69 List<Employee> employees = new ArrayList<>();
70
71 try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
72 String line = reader.readLine(); // Skip header
73
74 while ((line = reader.readLine()) != null) {
75 if (!line.trim().isEmpty()) {
76 try {
77 Employee emp = Employee.fromCSV(line);
78 employees.add(emp);
79 } catch (Exception e) {
80 System.err.println("Error parsing line: " + line + " - " + e.getMessage());
81 }
82 }
83 }
84
85 System.out.println("Successfully read " + employees.size() + " employees from " + filename);
86
87 } catch (IOException e) {
88 System.err.println("Error reading CSV file: " + e.getMessage());
89 }
90
91 return employees;
92 }
93
94 public static void analyzeEmployeeData(List<Employee> employees) {
95 System.out.println("\n=== Employee Data Analysis ===");
96
97 // Group by department
98 Map<String, List<Employee>> byDepartment = employees.stream()
99 .collect(Collectors.groupingBy(Employee::getDepartment));
100
101 System.out.println("Employees by department:");
102 byDepartment.forEach((dept, empList) -> {
103 double avgSalary = empList.stream()
104 .mapToDouble(Employee::getSalary)
105 .average()
106 .orElse(0.0);
107
108 System.out.printf("%s: %d employees, avg salary: $%.2f%n",
109 dept, empList.size(), avgSalary);
110 });
111
112 // Find highest paid employee
113 Employee highestPaid = employees.stream()
114 .max(Comparator.comparingDouble(Employee::getSalary))
115 .orElse(null);
116
117 if (highestPaid != null) {
118 System.out.println("Highest paid: " + highestPaid);
119 }
120
121 // Calculate overall statistics
122 DoubleSummaryStatistics salaryStats = employees.stream()
123 .mapToDouble(Employee::getSalary)
124 .summaryStatistics();
125
126 System.out.printf("Salary statistics: min=%.2f, max=%.2f, avg=%.2f%n",
127 salaryStats.getMin(), salaryStats.getMax(), salaryStats.getAverage());
128 }
129
130 public static void demonstrateCSVProcessing() {
131 List<Employee> employees = Arrays.asList(
132 new Employee("Alice Johnson", "Engineering", 95000, 5),
133 new Employee("Bob Smith", "Marketing", 67000, 3),
134 new Employee("Charlie Brown", "Engineering", 78000, 2),
135 new Employee("Diana Prince", "Sales", 82000, 4),
136 new Employee("Eve Wilson", "Engineering", 89000, 6),
137 new Employee("Frank Miller", "Marketing", 71000, 4),
138 new Employee("Grace Lee", "Sales", 76000, 3)
139 );
140
141 String csvFile = "employees.csv";
142
143 writeEmployeesToCSV(csvFile, employees);
144 List<Employee> readEmployees = readEmployeesFromCSV(csvFile);
145 analyzeEmployeeData(readEmployees);
146 }
147}Properties File Handling
1import java.io.*;
2import java.util.Properties;
3import java.util.Enumeration;
4
5public class PropertiesFileHandler {
6
7 public static void createConfigurationFile(String filename) {
8 System.out.println("=== Creating Configuration File ===");
9
10 Properties config = new Properties();
11
12 // Database configuration
13 config.setProperty("db.host", "localhost");
14 config.setProperty("db.port", "5432");
15 config.setProperty("db.name", "myapp");
16 config.setProperty("db.username", "admin");
17 config.setProperty("db.password", "secret123");
18
19 // Application settings
20 config.setProperty("app.name", "My Application");
21 config.setProperty("app.version", "1.2.3");
22 config.setProperty("app.debug", "true");
23 config.setProperty("app.max.connections", "100");
24
25 // Server configuration
26 config.setProperty("server.port", "8080");
27 config.setProperty("server.timeout", "30000");
28
29 try (FileOutputStream output = new FileOutputStream(filename)) {
30 config.store(output, "Application Configuration");
31 System.out.println("Configuration saved to " + filename);
32
33 } catch (IOException e) {
34 System.err.println("Error saving configuration: " + e.getMessage());
35 }
36 }
37
38 public static Properties loadConfigurationFile(String filename) {
39 System.out.println("\n=== Loading Configuration File ===");
40
41 Properties config = new Properties();
42
43 try (FileInputStream input = new FileInputStream(filename)) {
44 config.load(input);
45 System.out.println("Configuration loaded from " + filename);
46
47 // Display loaded properties
48 System.out.println("Loaded " + config.size() + " properties:");
49 Enumeration<Object> keys = config.keys();
50 while (keys.hasMoreElements()) {
51 String key = (String) keys.nextElement();
52 String value = config.getProperty(key);
53 System.out.println(" " + key + " = " + value);
54 }
55
56 } catch (IOException e) {
57 System.err.println("Error loading configuration: " + e.getMessage());
58 }
59
60 return config;
61 }
62
63 public static void updateConfiguration(String filename, String key, String value) {
64 System.out.println("\n=== Updating Configuration ===");
65
66 Properties config = new Properties();
67
68 // Load existing properties
69 try (FileInputStream input = new FileInputStream(filename)) {
70 config.load(input);
71 } catch (IOException e) {
72 System.err.println("Error loading existing configuration: " + e.getMessage());
73 return;
74 }
75
76 // Update property
77 String oldValue = config.getProperty(key);
78 config.setProperty(key, value);
79
80 // Save updated properties
81 try (FileOutputStream output = new FileOutputStream(filename)) {
82 config.store(output, "Updated Configuration");
83 System.out.println("Updated " + key + ": " + oldValue + " -> " + value);
84
85 } catch (IOException e) {
86 System.err.println("Error saving updated configuration: " + e.getMessage());
87 }
88 }
89
90 public static void demonstrateTypedPropertyAccess(Properties config) {
91 System.out.println("\n=== Typed Property Access ===");
92
93 // String properties
94 String appName = config.getProperty("app.name", "Unknown Application");
95 String dbHost = config.getProperty("db.host", "localhost");
96
97 // Integer properties
98 int serverPort = Integer.parseInt(config.getProperty("server.port", "8080"));
99 int maxConnections = Integer.parseInt(config.getProperty("app.max.connections", "50"));
100
101 // Boolean properties
102 boolean debugMode = Boolean.parseBoolean(config.getProperty("app.debug", "false"));
103
104 // Long properties
105 long timeout = Long.parseLong(config.getProperty("server.timeout", "30000"));
106
107 System.out.println("Application: " + appName);
108 System.out.println("Database Host: " + dbHost);
109 System.out.println("Server Port: " + serverPort);
110 System.out.println("Max Connections: " + maxConnections);
111 System.out.println("Debug Mode: " + debugMode);
112 System.out.println("Timeout: " + timeout + "ms");
113
114 // Validate configuration
115 if (serverPort < 1024 || serverPort > 65535) {
116 System.err.println("Warning: Invalid server port " + serverPort);
117 }
118
119 if (maxConnections <= 0) {
120 System.err.println("Warning: Invalid max connections " + maxConnections);
121 }
122 }
123
124 public static void demonstratePropertiesHandling() {
125 String configFile = "app.properties";
126
127 createConfigurationFile(configFile);
128 Properties config = loadConfigurationFile(configFile);
129 updateConfiguration(configFile, "app.version", "1.3.0");
130
131 // Reload to see changes
132 config = loadConfigurationFile(configFile);
133 demonstrateTypedPropertyAccess(config);
134 }
135}Performance Considerations and Best Practices
Buffered vs Unbuffered I/O
1import java.io.*;
2import java.nio.file.*;
3import java.util.ArrayList;
4import java.util.List;
5
6public class FileIOPerformance {
7
8 public static void compareReadPerformance(String filename, int iterations) {
9 System.out.println("=== Read Performance Comparison ===");
10
11 // Create test file
12 createTestFile(filename, 10000);
13
14 // Test unbuffered reading
15 long startTime = System.nanoTime();
16 for (int i = 0; i < iterations; i++) {
17 readFileUnbuffered(filename);
18 }
19 long unbufferedTime = System.nanoTime() - startTime;
20
21 // Test buffered reading
22 startTime = System.nanoTime();
23 for (int i = 0; i < iterations; i++) {
24 readFileBuffered(filename);
25 }
26 long bufferedTime = System.nanoTime() - startTime;
27
28 // Test NIO.2 reading
29 startTime = System.nanoTime();
30 for (int i = 0; i < iterations; i++) {
31 readFileNIO(filename);
32 }
33 long nioTime = System.nanoTime() - startTime;
34
35 System.out.printf("Unbuffered reading (%d iterations): %d ms%n",
36 iterations, unbufferedTime / 1_000_000);
37 System.out.printf("Buffered reading (%d iterations): %d ms%n",
38 iterations, bufferedTime / 1_000_000);
39 System.out.printf("NIO.2 reading (%d iterations): %d ms%n",
40 iterations, nioTime / 1_000_000);
41
42 double bufferedSpeedup = (double) unbufferedTime / bufferedTime;
43 double nioSpeedup = (double) unbufferedTime / nioTime;
44
45 System.out.printf("Buffered is %.2fx faster than unbuffered%n", bufferedSpeedup);
46 System.out.printf("NIO.2 is %.2fx faster than unbuffered%n", nioSpeedup);
47 }
48
49 private static void createTestFile(String filename, int lines) {
50 try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
51 for (int i = 1; i <= lines; i++) {
52 writer.println("This is line " + i + " with some content to make it longer");
53 }
54 } catch (IOException e) {
55 System.err.println("Error creating test file: " + e.getMessage());
56 }
57 }
58
59 private static List<String> readFileUnbuffered(String filename) {
60 List<String> lines = new ArrayList<>();
61 try (FileReader reader = new FileReader(filename)) {
62 StringBuilder line = new StringBuilder();
63 int character;
64
65 while ((character = reader.read()) != -1) {
66 if (character == '\n') {
67 lines.add(line.toString());
68 line = new StringBuilder();
69 } else {
70 line.append((char) character);
71 }
72 }
73
74 if (line.length() > 0) {
75 lines.add(line.toString());
76 }
77
78 } catch (IOException e) {
79 System.err.println("Error reading file: " + e.getMessage());
80 }
81 return lines;
82 }
83
84 private static List<String> readFileBuffered(String filename) {
85 List<String> lines = new ArrayList<>();
86 try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
87 String line;
88 while ((line = reader.readLine()) != null) {
89 lines.add(line);
90 }
91 } catch (IOException e) {
92 System.err.println("Error reading file: " + e.getMessage());
93 }
94 return lines;
95 }
96
97 private static List<String> readFileNIO(String filename) {
98 try {
99 return Files.readAllLines(Paths.get(filename));
100 } catch (IOException e) {
101 System.err.println("Error reading file: " + e.getMessage());
102 return new ArrayList<>();
103 }
104 }
105
106 public static void demonstrateBufferSizeImpact() {
107 System.out.println("\n=== Buffer Size Impact ===");
108
109 String filename = "large_test.txt";
110 createTestFile(filename, 50000);
111
112 int[] bufferSizes = {1024, 4096, 8192, 16384, 32768};
113
114 for (int bufferSize : bufferSizes) {
115 long startTime = System.nanoTime();
116 copyFileWithBuffer(filename, "copy_" + bufferSize + ".txt", bufferSize);
117 long endTime = System.nanoTime();
118
119 System.out.printf("Buffer size %d bytes: %d ms%n",
120 bufferSize, (endTime - startTime) / 1_000_000);
121 }
122 }
123
124 private static void copyFileWithBuffer(String source, String target, int bufferSize) {
125 try (InputStream input = new FileInputStream(source);
126 OutputStream output = new FileOutputStream(target)) {
127
128 byte[] buffer = new byte[bufferSize];
129 int bytesRead;
130
131 while ((bytesRead = input.read(buffer)) != -1) {
132 output.write(buffer, 0, bytesRead);
133 }
134
135 } catch (IOException e) {
136 System.err.println("Error copying file: " + e.getMessage());
137 }
138 }
139
140 public static void demonstratePerformanceTesting() {
141 compareReadPerformance("test_performance.txt", 100);
142 demonstrateBufferSizeImpact();
143 }
144}Error Handling and Resource Management
Comprehensive Error Handling
1import java.io.*;
2import java.nio.file.*;
3import java.util.List;
4
5public class FileErrorHandling {
6
7 public static void robustFileReading(String filename) {
8 System.out.println("=== Robust File Reading ===");
9
10 Path filePath = Paths.get(filename);
11
12 // Check file existence and permissions before attempting to read
13 if (!Files.exists(filePath)) {
14 System.err.println("File does not exist: " + filename);
15 return;
16 }
17
18 if (!Files.isReadable(filePath)) {
19 System.err.println("File is not readable: " + filename);
20 return;
21 }
22
23 if (Files.isDirectory(filePath)) {
24 System.err.println("Path is a directory, not a file: " + filename);
25 return;
26 }
27
28 try {
29 long fileSize = Files.size(filePath);
30 System.out.println("Reading file: " + filename + " (size: " + fileSize + " bytes)");
31
32 List<String> lines = Files.readAllLines(filePath);
33 System.out.println("Successfully read " + lines.size() + " lines");
34
35 // Process lines safely
36 for (int i = 0; i < Math.min(5, lines.size()); i++) {
37 System.out.println("Line " + (i + 1) + ": " + lines.get(i));
38 }
39
40 } catch (IOException e) {
41 System.err.println("I/O error reading file: " + e.getMessage());
42 } catch (OutOfMemoryError e) {
43 System.err.println("File too large to read into memory: " + e.getMessage());
44 } catch (SecurityException e) {
45 System.err.println("Security error accessing file: " + e.getMessage());
46 }
47 }
48
49 public static void safeFileWriting(String filename, List<String> data) {
50 System.out.println("\n=== Safe File Writing ===");
51
52 Path filePath = Paths.get(filename);
53 Path parentDir = filePath.getParent();
54
55 try {
56 // Ensure parent directory exists
57 if (parentDir != null && !Files.exists(parentDir)) {
58 Files.createDirectories(parentDir);
59 System.out.println("Created directory: " + parentDir);
60 }
61
62 // Check if we can write to the location
63 if (Files.exists(filePath) && !Files.isWritable(filePath)) {
64 System.err.println("File exists but is not writable: " + filename);
65 return;
66 }
67
68 // Create backup if file exists
69 Path backupPath = null;
70 if (Files.exists(filePath)) {
71 backupPath = Paths.get(filename + ".backup");
72 Files.copy(filePath, backupPath, StandardCopyOption.REPLACE_EXISTING);
73 System.out.println("Created backup: " + backupPath);
74 }
75
76 // Write to temporary file first
77 Path tempPath = Paths.get(filename + ".tmp");
78
79 try {
80 Files.write(tempPath, data);
81
82 // Atomic move to final location
83 Files.move(tempPath, filePath, StandardCopyOption.REPLACE_EXISTING);
84 System.out.println("Successfully wrote " + data.size() + " lines to " + filename);
85
86 // Remove backup on success
87 if (backupPath != null) {
88 Files.deleteIfExists(backupPath);
89 }
90
91 } catch (IOException e) {
92 // Restore backup on failure
93 if (backupPath != null && Files.exists(backupPath)) {
94 Files.move(backupPath, filePath, StandardCopyOption.REPLACE_EXISTING);
95 System.err.println("Write failed, restored backup");
96 }
97
98 // Clean up temporary file
99 Files.deleteIfExists(tempPath);
100 throw e;
101 }
102
103 } catch (IOException e) {
104 System.err.println("Error writing file: " + e.getMessage());
105 } catch (SecurityException e) {
106 System.err.println("Security error writing file: " + e.getMessage());
107 }
108 }
109
110 public static void demonstrateResourceManagement() {
111 System.out.println("\n=== Resource Management ===");
112
113 // Try-with-resources with multiple resources
114 String inputFile = "input.txt";
115 String outputFile = "output.txt";
116
117 // Create sample input file
118 try {
119 Files.write(Paths.get(inputFile), "Sample content for processing".getBytes());
120 } catch (IOException e) {
121 System.err.println("Error creating input file: " + e.getMessage());
122 return;
123 }
124
125 // Process file with proper resource management
126 try (BufferedReader reader = Files.newBufferedReader(Paths.get(inputFile));
127 BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputFile))) {
128
129 String line;
130 int lineNumber = 1;
131
132 while ((line = reader.readLine()) != null) {
133 // Process line
134 String processedLine = String.format("[%d] %s (processed)", lineNumber, line.toUpperCase());
135 writer.write(processedLine);
136 writer.newLine();
137 lineNumber++;
138 }
139
140 System.out.println("File processing completed successfully");
141
142 } catch (IOException e) {
143 System.err.println("Error processing file: " + e.getMessage());
144
145 // Clean up output file on error
146 try {
147 Files.deleteIfExists(Paths.get(outputFile));
148 } catch (IOException cleanupError) {
149 System.err.println("Error cleaning up output file: " + cleanupError.getMessage());
150 }
151 }
152 }
153
154 public static void demonstrateErrorHandling() {
155 // Test with non-existent file
156 robustFileReading("non_existent_file.txt");
157
158 // Create sample data for writing
159 List<String> sampleData = Arrays.asList(
160 "Line 1: Sample data",
161 "Line 2: More content",
162 "Line 3: Final line"
163 );
164
165 // Test safe file writing
166 safeFileWriting("test_output.txt", sampleData);
167
168 // Test successful reading
169 robustFileReading("test_output.txt");
170
171 demonstrateResourceManagement();
172 }
173}Best Practices Summary
File I/O Best Practices:
- Use try-with-resources for automatic resource management
- Choose appropriate I/O method:
- Use NIO.2 (
Filesclass) for simple operations - Use buffered streams for large files
- Use binary streams for non-text data
- Use NIO.2 (
- Handle exceptions appropriately - distinguish between different error types
- Validate inputs - check file existence, permissions, and sizes
- Use proper encoding - specify charset explicitly (UTF-8 recommended)
- Consider memory usage - use streaming for large files
- Implement atomic operations - write to temp file then move
- Create backups for critical file modifications
Common Pitfalls:
- Not closing resources properly (use try-with-resources)
- Ignoring character encoding (causes corruption)
- Reading entire large files into memory (use streaming)
- Not handling IOException properly
- Platform-dependent path separators (use
PathAPI) - Not checking file permissions before operations
- Modifying files in-place without backups
Java’s file I/O capabilities have evolved significantly, providing developers with powerful, flexible tools for handling files efficiently and safely. Choose the right approach based on your specific requirements and always implement proper error handling and resource management.
← Previous: Collections Framework Next: Threads & Concurrency →