[Java Backend Zero to Hello] [Phase 2] BÀI 2.8: I/O & FILE
📚 Series: Java Backend Zero to Hello 📂 Phân đoạn: Phase 2: Java Core nâng cao 📖 Nội dung: BÀI 2.8: I/O & FILE 💡 Khóa học lập trình Backend Java & Spring Boot chuẩn doanh nghiệp từ con số 0.
BÀI 2.8: I/O & FILE
Mục tiêu
- Đọc/ghi file với Java I/O
- Sử dụng NIO.2 (Java 7+)
- Thao tác với Path và Files
- Serialization
1. HỆ THỐNG I/O
1.1 java.io (Cổ điển)
- Stream-based
- Blocking I/O
- Phù hợp với file nhỏ
1.2 java.nio (New I/O)
- Buffer-based
- Non-blocking I/O
- Hiệu năng cao hơn
1.3 java.nio.file (NIO.2 - Java 7+)
- API hiện đại cho file
- Hỗ trợ filesystem operations
2. JAVA.IO CƠ BẢN
2.1 Byte Stream
Đọc/ghi dữ liệu nhị phân.
import java.io.*;
// Đọc file
try (FileInputStream fis = new FileInputStream("data.bin");
BufferedInputStream bis = new BufferedInputStream(fis)) {
int byteData;
while ((byteData = bis.read()) != -1) {
System.out.print((char) byteData);
}
}
// Ghi file
try (FileOutputStream fos = new FileOutputStream("output.bin");
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
String data = "Hello World";
bos.write(data.getBytes());
}
2.2 Character Stream
Đọc/ghi văn bản (tự xử lý encoding).
// Đọc file text
try (FileReader fr = new FileReader("data.txt");
BufferedReader br = new BufferedReader(fr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
// Ghi file text
try (FileWriter fw = new FileWriter("output.txt");
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write("Hello World");
bw.newLine();
bw.write("Dòng 2");
}
2.3 PrintWriter
try (PrintWriter pw = new PrintWriter(new FileWriter("output.txt"))) {
pw.println("Hello");
pw.printf("Tuổi: %d%n", 25);
pw.printf("Tên: %s%n", "An");
}
3. NIO.2 (JAVA 7+)
3.1 Path
import java.nio.file.Path;
import java.nio.file.Paths;
Path path1 = Paths.get("data.txt");
Path path2 = Paths.get("C:", "Users", "Admin", "data.txt");
Path path3 = Paths.get("C:\\Users\\Admin\\data.txt");
// Thông tin
path1.getFileName(); // data.txt
path1.getParent(); // null (file ở root)
path1.getRoot(); // null
path1.toAbsolutePath(); // Đường dẫn tuyệt đối
path1.toString(); // data.txt
3.2 Files - Đọc/Ghi
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
// Đọc tất cả
byte[] bytes = Files.readAllBytes(Paths.get("data.bin"));
List<String> lines = Files.readAllLines(Paths.get("data.txt"));
String content = Files.readString(Paths.get("data.txt")); // Java 11+
// Ghi
Files.write(Paths.get("output.txt"), "Hello".getBytes());
Files.write(Paths.get("output.txt"), lines);
Files.writeString(Paths.get("output.txt"), "Hello World"); // Java 11+
// Append
Files.write(Paths.get("log.txt"), "New line\n".getBytes(),
StandardOpenOption.APPEND);
3.3 Files - Thao tác
// Copy
Files.copy(Paths.get("source.txt"), Paths.get("dest.txt"),
StandardCopyOption.REPLACE_EXISTING);
// Move
Files.move(Paths.get("source.txt"), Paths.get("dest.txt"),
StandardCopyOption.REPLACE_EXISTING);
// Delete
Files.delete(Paths.get("file.txt")); // Ném exception nếu không tồn tại
Files.deleteIfExists(Paths.get("file.txt")); // Không ném exception
// Tạo
Files.createFile(Paths.get("new.txt"));
Files.createDirectory(Paths.get("newdir"));
Files.createDirectories(Paths.get("a/b/c")); // Tạo cả cây thư mục
// Thông tin
boolean exists = Files.exists(Paths.get("file.txt"));
boolean isDir = Files.isDirectory(Paths.get("dir"));
long size = Files.size(Paths.get("file.txt"));
FileTime lastModified = Files.getLastModifiedTime(Paths.get("file.txt"));
3.4 Directory Stream
try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get("."))) {
for (Path entry : stream) {
System.out.println(entry.getFileName());
}
}
// Filter
try (DirectoryStream<Path> stream = Files.newDirectoryStream(
Paths.get("."), "*.txt")) {
for (Path entry : stream) {
System.out.println(entry.getFileName());
}
}
3.5 Walk - Duyệt cây thư mục
// Duyệt tất cả file
Stream<Path> walk = Files.walk(Paths.get("."));
walk.filter(Files::isRegularFile)
.forEach(System.out::println);
// Tìm file
try (Stream<Path> walk = Files.walk(Paths.get("."))) {
List<Path> javaFiles = walk
.filter(p -> p.toString().endsWith(".java"))
.collect(Collectors.toList());
}
4. SERIALIZATION
Chuyển object thành byte stream để lưu trữ hoặc truyền qua mạng.
4.1 Serializable
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String password; // Không serialize
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
4.2 Serialize
User user = new User("An", 25);
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("user.ser"))) {
oos.writeObject(user);
}
4.3 Deserialize
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("user.ser"))) {
User user = (User) ois.readObject();
System.out.println(user.getName());
}
5. ĐỌC/GHI CSV
// Đọc CSV
List<String[]> data = Files.readAllLines(Paths.get("data.csv"))
.stream()
.map(line -> line.split(","))
.collect(Collectors.toList());
// Ghi CSV
List<String> lines = users.stream()
.map(u -> u.getId() + "," + u.getName() + "," + u.getEmail())
.collect(Collectors.toList());
Files.write(Paths.get("users.csv"), lines);
6. ĐỌC/GHI JSON (với thư viện)
Trong thực tế, dùng Jackson hoặc Gson:
// Với Jackson
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new File("user.json"), User.class);
mapper.writeValue(new File("user.json"), user);
7. BÀI TẬP THỰC HÀNH
Bài 1: Đọc file log
public List<String> readLogFile(String path) throws IOException {
return Files.readAllLines(Paths.get(path));
}
public List<String> filterErrors(String path) throws IOException {
return Files.lines(Paths.get(path))
.filter(line -> line.contains("ERROR"))
.collect(Collectors.toList());
}
Bài 2: Copy thư mục
public void copyDirectory(Path source, Path target) throws IOException {
Files.walk(source).forEach(src -> {
Path dest = target.resolve(source.relativize(src));
try {
Files.copy(src, dest, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
Bài 3: Tìm file lớn nhất
public Optional<Path> findLargestFile(Path dir) throws IOException {
try (Stream<Path> walk = Files.walk(dir)) {
return walk
.filter(Files::isRegularFile)
.max(Comparator.comparingLong(p -> {
try {
return Files.size(p);
} catch (IOException e) {
return 0L;
}
}));
}
}
Bài 4: Word count
public Map<String, Long> wordCount(Path file) throws IOException {
return Files.lines(file)
.flatMap(line -> Arrays.stream(line.split("\\s+")))
.collect(Collectors.groupingBy(
String::toLowerCase,
Collectors.counting()
));
}
8. TÓM TẮT
| API | Mô tả |
|---|---|
FileInputStream / FileOutputStream |
Byte stream |
FileReader / FileWriter |
Character stream |
BufferedReader / BufferedWriter |
Buffered (hiệu quả hơn) |
Path / Paths |
Đường dẫn (NIO.2) |
Files |
Thao tác file (NIO.2) |
Serializable |
Tuần tự hóa object |
ObjectInputStream / ObjectOutputStream |
Serialize/Deserialize |
Bài tiếp theo: 2.9 Annotation & Reflection
🧭 Điều hướng bài học
- ⬅️ Bài trước: BÀI 2.7: EXECUTOR FRAMEWORK
- ➡️ Bài tiếp theo: BÀI 2.9: ANNOTATION & REFLECTION
- 📑 Toàn bộ lộ trình: Java Backend Zero to Hello
⭐ Hãy bookmark (clip) lại series để tiện theo dõi các bài học tiếp theo nhé!
All rights reserved