File Handling and I/O Operations
Read/write files in Java. Master standard streams, Reader/Writer classes, buffer filters, NIO file systems, and serialization.
Downloaded from PrepIQ (https://prepiq.online)
Q1. What is File I/O in Java and why is it important?
File I/O (Input/Output) allows Java applications to read from and write to files on disk. It's essential for data persistence, log management, configuration handling, and inter-process communication.
| Type | Purpose | Example |
|---|---|---|
| Input (Reading) | Read data from file to memory | FileInputStream, FileReader |
| Output (Writing) | Write data from memory to file | FileOutputStream, FileWriter |
| Byte-Based | Binary data processing | InputStream, OutputStream |
| Character-Based | Text data processing | Reader, Writer |
// Basic File I/O Example
import java.io.*;
public class FileIODemo {
public static void main(String[] args) {
// Writing to file
try (FileWriter fw = new FileWriter('data.txt')) {
fw.write('Hello, File I/O!');
} catch (IOException e) {
e.printStackTrace();
}
// Reading from file
try (FileReader fr = new FileReader('data.txt')) {
int character;
while ((character = fr.read()) != -1) {
System.out.print((char) character);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Benefits of File I/O:
// 1. Persistent storage - data survives application restart
// 2. Data exchange - share data between applications
// 3. Logging - record application events
// 4. Configuration - load app settings from files
// 5. Backup - create file backups
Q2. What is the File class in Java and its important methods?
The File class represents file and directory pathnames. It provides methods to check file properties, create files/directories, delete files, and list directory contents.
import java.io.File;
public class FileClassDemo {
public static void main(String[] args) {
File file = new File('example.txt');
// Check file properties
System.out.println('Exists: ' + file.exists());
System.out.println('Is file: ' + file.isFile());
System.out.println('Is directory: ' + file.isDirectory());
System.out.println('Can read: ' + file.canRead());
System.out.println('Can write: ' + file.canWrite());
System.out.println('File size: ' + file.length());
System.out.println('Absolute path: ' + file.getAbsolutePath());
// Create file
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
// List files in directory
File dir = new File('.');
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
System.out.println(f.getName());
}
}
// Delete file
file.delete();
// Create directory
File newDir = new File('myDir');
newDir.mkdir();
// Get parent directory
File parent = file.getParentFile();
System.out.println('Parent: ' + parent.getPath());
}
}
Q3. What are FileReader and FileWriter? How do you use them for text files?
FileReader reads character data from files, while FileWriter writes character data to files. They are character-based streams ideal for text file processing.
import java.io.*;
public class FileReaderWriterDemo {
public static void main(String[] args) {
// Writing text to file using FileWriter
try (FileWriter writer = new FileWriter('output.txt')) {
writer.write('Line 1: Hello World\n');
writer.write('Line 2: Java File I/O\n');
writer.write('Line 3: File Processing\n');
System.out.println('File written successfully');
} catch (IOException e) {
e.printStackTrace();
}
// Reading text from file using FileReader
try (FileReader reader = new FileReader('output.txt')) {
int character;
StringBuilder content = new StringBuilder();
while ((character = reader.read()) != -1) {
content.append((char) character);
}
System.out.println('File content:\n' + content.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Best Practice: Use try-with-resources
// Automatically closes file, even if exception occurs
try (FileWriter fw = new FileWriter('file.txt')) {
fw.write('Content');
} catch (IOException e) {
e.printStackTrace();
}
// Note: FileReader/FileWriter work with default charset
// For specific charset, use InputStreamReader/OutputStreamWriter
Q4. What are BufferedReader and BufferedWriter? Why use them instead of plain readers?
BufferedReader and BufferedWriter provide buffering on top of character streams. They read/write data in chunks (buffer), which is much faster than reading character-by-character.
import java.io.*;
public class BufferedIODemo {
public static void main(String[] args) {
// Writing with BufferedWriter (faster)
try (BufferedWriter bw = new BufferedWriter(
new FileWriter('data.txt'))) {
bw.write('Line 1: First line');
bw.newLine();
bw.write('Line 2: Second line');
bw.newLine();
bw.write('Line 3: Third line');
bw.flush(); // Force write to disk
} catch (IOException e) {
e.printStackTrace();
}
// Reading with BufferedReader (faster)
try (BufferedReader br = new BufferedReader(
new FileReader('data.txt'))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Performance Comparison
// FileReader: Reads 1 character at a time
// BufferedReader: Reads buffer (8192 chars) at a time
// Result: BufferedReader is 100x+ faster for large files
// Common BufferedReader methods
BufferedReader br = new BufferedReader(new FileReader('file.txt'));
String line = br.readLine(); // Read one line
int character = br.read(); // Read one character
char[] buffer = new char[1024];
int charsRead = br.read(buffer); // Read into buffer
br.close();
// Common BufferedWriter methods
BufferedWriter bw = new BufferedWriter(new FileWriter('file.txt'));
bw.write('Text'); // Write string
bw.write('A'); // Write character
bw.newLine(); // Write newline
bw.flush(); // Flush buffer to disk
bw.close();
Q5. What are FileInputStream and FileOutputStream for binary files?
FileInputStream reads binary data from files, while FileOutputStream writes binary data to files. They work with bytes instead of characters, making them suitable for images, videos, and binary files.
import java.io.*;
public class BinaryFileDemo {
public static void main(String[] args) {
// Writing binary data
try (FileOutputStream fos = new FileOutputStream('binary.bin')) {
byte[] data = {65, 66, 67, 68, 69}; // ABCDE
fos.write(data); // Write entire array
fos.write(70); // Write single byte
System.out.println('Binary file written');
} catch (IOException e) {
e.printStackTrace();
}
// Reading binary data
try (FileInputStream fis = new FileInputStream('binary.bin')) {
int byte_value;
while ((byte_value = fis.read()) != -1) {
System.out.print((char) byte_value + ' ');
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Copy binary file (image, video, etc.)
public class FileCopyDemo {
public static void copyFile(String source, String destination) {
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(destination)) {
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) {
e.printStackTrace();
}
}
public static void main(String[] args) {
copyFile('source.jpg', 'destination.jpg');
}
}
// FileInputStream methods
FileInputStream fis = new FileInputStream('file.bin');
int byte_val = fis.read(); // Read single byte (-1 if EOF)
byte[] buffer = new byte[1024];
int bytesRead = fis.read(buffer); // Read into buffer
long skipped = fis.skip(100); // Skip bytes
fis.close();
// FileOutputStream methods
FileOutputStream fos = new FileOutputStream('file.bin');
fos.write(65); // Write single byte
fos.write(new byte[]{65, 66, 67}); // Write array
fos.flush(); // Flush to disk
fos.close();
Q6. What is Object Serialization in Java and how do you use it?
Serialization converts Java objects into byte stream format for storage or transmission. Deserialization reconstructs objects from byte stream. It's essential for persistence and network communication.
import java.io.*;
// Step 1: Make class Serializable
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
private double gpa;
public Student(int id, String name, double gpa) {
this.id = id;
this.name = name;
this.gpa = gpa;
}
@Override
public String toString() {
return 'Student{' + 'id=' + id + ', name=' + name +
', gpa=' + gpa + '}';
}
}
// Step 2: Serialize objects
public class SerializationDemo {
public static void main(String[] args) {
// Serialization (Object to File)
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream('student.ser'))) {
Student s1 = new Student(1, 'John', 3.8);
Student s2 = new Student(2, 'Jane', 3.9);
oos.writeObject(s1);
oos.writeObject(s2);
System.out.println('Objects serialized');
} catch (IOException e) {
e.printStackTrace();
}
// Deserialization (File to Object)
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream('student.ser'))) {
Student st1 = (Student) ois.readObject();
Student st2 = (Student) ois.readObject();
System.out.println(st1);
System.out.println(st2);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
// Important: serialVersionUID
// Version identifier for serialization
// Change when class structure changes
private static final long serialVersionUID = 1L;
// Transient keyword - exclude field from serialization
public class User implements Serializable {
private String username;
private transient String password; // Not serialized
}
// Collections serialization
List<Student> students = new ArrayList<>();
students.add(new Student(1, 'John', 3.8));
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream('students.ser'))) {
oos.writeObject(students);
}
Q7. What is try-with-resources statement and why is it important for file I/O?
Try-with-resources automatically closes resources (files, streams) even if exceptions occur. It prevents resource leaks and makes code cleaner. Available since Java 7.
// OLD way (manual close needed)
FileReader reader = null;
try {
reader = new FileReader('file.txt');
// Read from file
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close(); // Easy to forget!
} catch (IOException e) {
e.printStackTrace();
}
}
}
// NEW way (Java 7+) - try-with-resources
try (FileReader reader = new FileReader('file.txt')) {
int ch;
while ((ch = reader.read()) != -1) {
System.out.print((char) ch);
}
} catch (IOException e) {
e.printStackTrace();
}
// Automatically closes reader
// Multiple resources
try (FileReader fr = new FileReader('input.txt');
FileWriter fw = new FileWriter('output.txt')) {
int ch;
while ((ch = fr.read()) != -1) {
fw.write(ch);
}
} catch (IOException e) {
e.printStackTrace();
}
// Both files automatically closed
// Custom AutoCloseable class
public class DatabaseConnection implements AutoCloseable {
@Override
public void close() throws Exception {
System.out.println('Connection closed');
}
public void query(String sql) {
System.out.println('Executing: ' + sql);
}
}
// Using custom AutoCloseable
try (DatabaseConnection db = new DatabaseConnection()) {
db.query('SELECT * FROM users');
} catch (Exception e) {
e.printStackTrace();
}
// Connection automatically closed
// Benefits:
// 1. Automatic resource cleanup
// 2. No resource leaks
// 3. Exception handling during close
// 4. Cleaner code
// 5. Safe concurrent access
Q8. What is Character Encoding in file I/O? How do you handle different charsets?
Character encoding specifies how characters are represented as bytes. Different encodings (UTF-8, UTF-16, ASCII, ISO-8859-1) store characters differently. Incorrect encoding causes garbled text.
import java.io.*;
import java.nio.charset.StandardCharsets;
public class CharsetDemo {
public static void main(String[] args) {
String text = 'Hello, 你好, नमस्ते';
// Writing with specific charset
try (FileWriter fw = new FileWriter('utf8.txt',
StandardCharsets.UTF_8)) {
fw.write(text);
System.out.println('UTF-8 file written');
} catch (IOException e) {
e.printStackTrace();
}
// Reading with specific charset
try (FileReader fr = new FileReader('utf8.txt',
StandardCharsets.UTF_8)) {
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
} catch (IOException e) {
e.printStackTrace();
}
// Using InputStreamReader for charset control
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream('file.txt'),
StandardCharsets.UTF_8)) {
BufferedReader br = new BufferedReader(isr);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
// Using OutputStreamWriter for charset control
try (OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream('output.txt'),
StandardCharsets.UTF_8)) {
osw.write('Multilingual text: Hello, 世界, мир');
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Common charsets
// UTF-8: Variable-length encoding (1-4 bytes per character)
// UTF-16: Fixed 2-byte encoding
// ASCII: 7-bit encoding (English only)
// ISO-8859-1: European characters
// GBK: Chinese characters
// Detect encoding
public class EncodingDetection {
public static String detectEncoding(File file) {
// Using Apache Commons IO or ICU4J libraries
// Or detect BOM (Byte Order Mark)
return 'UTF-8';
}
}
Q9. What are NIO (New I/O) Channels and Buffers? How are they different from traditional I/O?
NIO (java.nio) provides channels and buffers for faster, non-blocking file I/O. Channels are two-way, support multiplexing, and work with buffers for bulk data transfer. Better performance for large files.
import java.io.*;
import java.nio.file.*;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;
public class NIODemo {
public static void main(String[] args) {
// Copy file using NIO (faster)
copyFileUsingNIO('source.txt', 'destination.txt');
}
public static void copyFileUsingNIO(String source, String dest) {
try (FileInputStream fis = new FileInputStream(source);
FileOutputStream fos = new FileOutputStream(dest);
FileChannel inChannel = fis.getChannel();
FileChannel outChannel = fos.getChannel()) {
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (inChannel.read(buffer) > 0) {
buffer.flip();
outChannel.write(buffer);
buffer.clear();
}
System.out.println('File copied using NIO');
} catch (IOException e) {
e.printStackTrace();
}
}
}
// NIO vs Traditional I/O
// Traditional: Stream-based, blocking, single direction
// NIO: Channel-based, non-blocking, bidirectional
// Using Files utility class (Java 7+)
public class FilesAPIDemo {
public static void main(String[] args) {
try {
// Read all lines
List<String> lines = Files.readAllLines(
Paths.get('file.txt'));
// Write lines
Files.write(Paths.get('output.txt'),
'New content'.getBytes());
// Copy file
Files.copy(Paths.get('source.txt'),
Paths.get('dest.txt'));
// Walk directory
Files.walk(Paths.get('.'))
.filter(Files::isRegularFile)
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
// ByteBuffer operations
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put(new byte[]{65, 66, 67}); // Write to buffer
buffer.flip(); // Switch to read mode
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
buffer.clear(); // Clear for next use
Q10. What are common patterns and best practices for file handling in Java?
Best practices for file I/O include using try-with-resources, buffering, proper exception handling, checking file existence, and choosing appropriate streams based on data type.
import java.io.*;
import java.nio.file.*;
import java.util.*;
public class FileHandlingBestPractices {
// Pattern 1: Reading file line by line
public static void readFileLinesPattern(String filePath) {
try (BufferedReader reader = new BufferedReader(
new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println('Error reading file: ' + e.getMessage());
}
}
// Pattern 2: Writing content to file
public static void writeFilePattern(String filePath, String content) {
try (BufferedWriter writer = new BufferedWriter(
new FileWriter(filePath))) {
writer.write(content);
writer.flush();
} catch (IOException e) {
System.err.println('Error writing file: ' + e.getMessage());
}
}
// Pattern 3: Safe file operations
public static void safeFileOperations(String filePath) {
File file = new File(filePath);
// Check before operations
if (!file.exists()) {
System.out.println('File does not exist');
return;
}
if (!file.canRead()) {
System.out.println('File not readable');
return;
}
if (file.length() > 10_000_000) {
System.out.println('File too large');
return;
}
// Process file
}
// Pattern 4: Efficient batch processing
public static void processLargeFileEfficiently(String filePath) {
try (BufferedReader reader = new BufferedReader(
new FileReader(filePath), 65536)) { // 64KB buffer
String line;
while ((line = reader.readLine()) != null) {
// Process line
}
} catch (IOException e) {
e.printStackTrace();
}
}
// Pattern 5: Using Java 7+ Files API
public static void modernFileHandling(String filePath) {
try {
// Read entire file
List<String> lines = Files.readAllLines(Paths.get(filePath));
// Process
lines.stream()
.filter(line -> !line.isEmpty())
.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
// Pattern 6: Error handling and logging
public static void robustFileHandling(String filePath) {
try (BufferedReader reader = new BufferedReader(
new FileReader(filePath))) {
String line;
int lineNo = 0;
while ((line = reader.readLine()) != null) {
lineNo++;
try {
// Process line
} catch (Exception e) {
System.err.println('Error at line ' + lineNo + ': ' + e);
}
}
} catch (FileNotFoundException e) {
System.err.println('File not found: ' + filePath);
} catch (IOException e) {
System.err.println('IO error: ' + e.getMessage());
}
}
}
// Best Practices Summary:
// 1. Always use try-with-resources
// 2. Use BufferedReader/Writer for text (faster)
// 3. Use FileInputStream/OutputStream for binary
// 4. Check file existence and permissions before use
// 5. Validate file size before reading
// 6. Use appropriate buffer sizes
// 7. Handle specific exceptions (FileNotFoundException, etc.)
// 8. Close resources explicitly if not using try-with-resources
// 9. Log errors appropriately
// 10. Use Files API for Java 7+ applications
File Handling and I/O Operations
Read/write files in Java. Master standard streams, Reader/Writer classes, buffer filters, NIO file systems, and serialization.
What is File I/O in Java and why is it important?
File I/O (Input/Output) allows Java applications to read from and write to files on disk. It's essential for d...
What is the File class in Java and its important methods?
The File class represents file and directory pathnames. It provides methods to check file properties, create f...
What are FileReader and FileWriter? How do you use them for text files?
FileReader reads character data from files, while FileWriter writes character data to files. They are characte...
What are BufferedReader and BufferedWriter? Why use them instead of plain readers?
BufferedReader and BufferedWriter provide buffering on top of character streams. They read/write data in chunk...
What are FileInputStream and FileOutputStream for binary files?
FileInputStream reads binary data from files, while FileOutputStream writes binary data to files. They work wi...
What is Object Serialization in Java and how do you use it?
Serialization converts Java objects into byte stream format for storage or transmission. Deserialization recon...
What is try-with-resources statement and why is it important for file I/O?
Try-with-resources automatically closes resources (files, streams) even if exceptions occur. It prevents resou...
What is Character Encoding in file I/O? How do you handle different charsets?
Character encoding specifies how characters are represented as bytes. Different encodings (UTF-8, UTF-16, ASCI...
What are NIO (New I/O) Channels and Buffers? How are they different from traditional I/O?
NIO (java.nio) provides channels and buffers for faster, non-blocking file I/O. Channels are two-way, support...
What are common patterns and best practices for file handling in Java?
Best practices for file I/O include using try-with-resources, buffering, proper exception handling, checking f...