IO
Reading from a File
The FileInputStream class is used to read raw bytes from a file. If you're reading character data (like text), it's better to use FileReader.
import java.io.FileInputStream;
import java.io.IOException;
public class ReadFile {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input.txt")) {
int data;
while ((data = fis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Writing to a File
The FileOutputStream class is used to write raw bytes to a file. For writing character data, use FileWriter.
import java.io.FileOutputStream;
import java.io.IOException;
public class WriteFile {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
String content = "Hello, World!";
fos.write(content.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Using Buffered Streams
Buffered streams read or write data in large chunks rather than one byte/character at a time. This often leads to faster I/O.
For reading:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReadFile {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("input.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
For writing:
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriteFile {
public static void main(String[] args) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
String content = "Hello, World!";
bw.write(content);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Tips: - Always close your streams after use to free up system resources. Using try-with-resources, as shown in the examples, helps ensure streams are closed automatically. - If you're working with text files and care about character encoding, consider using InputStreamReader and OutputStreamWriter as they allow specifying a charset. - For large files, it's beneficial to use buffered streams as they can improve performance.
Java provides a clear distinction between byte-oriented streams (for binary data) and character-oriented streams (for text data). The Reader and Writer abstract classes in the java.io package form the foundation of character-oriented streams. They handle the encoding and decoding automatically, making text I/O operations more intuitive.
FileReader
Reads text files. It uses the default character encoding unless otherwise specified.
try (FileReader fr = new FileReader("file.txt")) {
int c;
while ((c = fr.read()) != -1) {
System.out.print((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}
StringReader
Allows reading from a string as if it were a stream.
String data = "Hello, World!";
try (StringReader sr = new StringReader(data)) {
int c;
while ((c = sr.read()) != -1) {
System.out.print((char) c);
}
} catch (IOException e) {
e.printStackTrace();
}
BufferedReader
Reads text from a character input stream, buffering characters to provide efficient reading of characters, arrays, and lines.
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
FileWriter
Writes to text files. It uses the default character encoding unless otherwise specified.
try (FileWriter fw = new FileWriter("file.txt")) {
fw.write("Hello, World!");
} catch (IOException e) {
e.printStackTrace();
}
StringWriter
Allows writing to a string as if it were a stream.
try (StringWriter sw = new StringWriter()) {
sw.write("Hello, World!");
System.out.println(sw.toString());
} catch (IOException e) {
e.printStackTrace();
}
BufferedWriter
Writes text to a character output stream, buffering characters to provide efficient writing of single characters, arrays, and strings.
try (BufferedWriter bw = new BufferedWriter(new FileWriter("file.txt"))) {
bw.write("Hello, World!");
} catch (IOException e) {
e.printStackTrace();
}
Best Practices
- When reading or writing text data, prefer using Reader and Writer classes because they handle character encodings transparently.
- Always close your streams (or use try-with-resources) to prevent resource leaks.
- For most general uses, BufferedReader and BufferedWriter are recommended because they perform buffering, which can significantly speed up I/O operations._
Path
The Path interface represents a file or directory's location in the file system. You can obtain a Path instance using the Paths utility class.
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathExample {
public static void main(String[] args) {
Path path = Paths.get("path/to/file.txt");
System.out.println(path);
}
}
Files
The Files class provides a suite of methods to manipulate files and directories.
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.List;
public class ReadFile {
public static void main(String[] args) {
Path path = Paths.get("path/to/file.txt");
try {
List<String> lines = Files.readAllLines(path);
for (String line : lines) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Write to a file:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class WriteFile {
public static void main(String[] args) {
Path path = Paths.get("path/to/file.txt");
List<String> content = Arrays.asList("Hello", "World!");
try {
Files.write(path, content);
} catch (IOException e) {
e.printStackTrace();
}
}
}
useful methods:
-
Check if file exists:
boolean exists = Files.exists(path);
-
Copy a file:
Path source = Paths.get("source.txt"); Path target = Paths.get("target.txt"); Files.copy(source, target);
-
Delete a file:
Files.delete(path);
-
Move/rename a file:
Path source = Paths.get("source.txt"); Path target = Paths.get("target.txt"); Files.move(source, target);
-
Create a directory:
Path dir = Paths.get("path/to/directory"); Files.createDirectory(dir);
Advantages of the java.nio.file API:
- Flexibility: Provides better control and more features for file operations.
- Performance: Some operations can be more efficient, especially when using BufferedReader or BufferedWriter from java.nio.file.
- Symbolic link support: It has in-built methods to handle symbolic links in a file system.
- Atomic operations: Some operations like createFile or createDirectory can be atomic, helping prevent certain types of bugs.
Exercises
Basic File Read and Write
Task: Write a program that reads content from an input file and writes it to an output file.
Read from input.txt Write to output.txt
Uppercase Converter
Task: Read a file, convert all its contents to uppercase, and then write the result to another file.
Read from lowercase.txt Convert the content to uppercase Write the converted content to uppercase.txt
Word Counter
Task: Read a file and count the number of words in it. Print the count to the console.
Line Reverser
Task: Read a text file and write its content to another file such that the order of lines in the output file is the reverse of the input file.
Binary File Copy
Task: Copy a binary file (e.g., an image or audio file) using FileInputStream and FileOutputStream.
Read from source.jpg Write to destination.jpg
Buffered Read and Write
Task: Use BufferedReader and BufferedWriter to read a file and write its content to another file.
Filter Words
Task: Read a text file and write only the words longer than 5 characters to another file.
Replace Word
Task: Read a file, replace every occurrence of the word "Java" with "Python", and write the result to another file.
Merge Multiple Files
Task: Merge the content of multiple text files into a single file.
Read from file1.txt, file2.txt, and file3.txt Write merged content to merged.txt
Count Occurrences
Task: Read a file and count the number of occurrences of a specific word (case-insensitive).
Tip: Use a function and pass the word as an argument to make it reusable.
Solutions
Basic File Read and Write
import java.io.*;
public class BasicReadWrite {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("input.txt");
FileWriter fw = new FileWriter("output.txt");
int c;
while ((c = fr.read()) != -1) {
fw.write(c);
}
fr.close();
fw.close();
}
}
Uppercase Converter
public class UppercaseConverter {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("lowercase.txt");
FileWriter fw = new FileWriter("uppercase.txt");
int c;
while ((c = fr.read()) != -1) {
fw.write(Character.toUpperCase(c));
}
fr.close();
fw.close();
}
}
Word Counter
public class WordCounter {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
String line;
int wordCount = 0;
while ((line = br.readLine()) != null) {
wordCount += line.split("\\s+").length;
}
System.out.println("Word count: " + wordCount);
br.close();
}
}
Line Reverser
import java.util.*;
public class LineReverser {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
List<String> lines = new ArrayList<>();
String line;
while ((line = br.readLine()) != null) {
lines.add(line);
}
Collections.reverse(lines);
BufferedWriter bw = new BufferedWriter(new FileWriter("reversed.txt"));
for (String l : lines) {
bw.write(l);
bw.newLine();
}
br.close();
bw.close();
}
}
Binary File Copy
public class BinaryFileCopy {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("source.jpg");
FileOutputStream fos = new FileOutputStream("destination.jpg");
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
fis.close();
fos.close();
}
}
Buffered Read and Write
(Quite similar to Basic File Read and Write but uses buffered streams for efficiency)
public class BufferedReadWrite {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
br.close();
bw.close();
}
}
Filter Words
public class FilterWords {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("filtered.txt"));
String line;
while ((line = br.readLine()) != null) {
for (String word : line.split("\\s+")) {
if (word.length() > 5) {
bw.write(word);
bw.newLine();
}
}
}
br.close();
bw.close();
}
}
Replace Word
public class ReplaceWord {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("input.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("replaced.txt"));
String line;
while ((line = br.readLine()) != null) {
bw.write(line.replace("Java", "Python"));
bw.newLine();
}
br.close();
bw.close();
}
}
Merge Multiple Files
public class MergeFiles {
public static void main(String[] args) throws IOException {
String[] fileNames = {"file1.txt", "file2.txt", "file3.txt"};
BufferedWriter bw = new BufferedWriter(new FileWriter("merged.txt"));
for (String fileName : fileNames) {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
br.close();
}
bw.close();
}
}
Count Occurrences
public class CountOccurrences {
public static void main(String[] args) throws IOException {
System.out.println(countWord("input.txt", "Java"));
}
public static int countWord(String fileName, String word) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line;
int count = 0;
while ((line = br.readLine()) != null) {
for (String w : line.split("\\s+")) {
if (w.equalsIgnoreCase(word)) {
count++;
}
}
}
br.close();
return count;
}
}