Trong bài viết này, bạn sẽ tìm hiểu vềcách đọc file trong Java theo từng dòng với nhiều cách khác nhau.

Bài viết này sẽ sử dụng các phương thức từ những Java classes sau: java.io.BufferedReader, java.util.Scanner, Files.readAllLines(), và java.io.RandomAccessFile.
Đọc file theo từng dòng bằng BufferedReader
Bạn có thể sử dụng phương thức readLine() từ **j**ava.io.BufferedReader để đọc file theo từng dòng và lưu vào String. Phương thức này sẽ trả về null khi đọc đến cuối file.
Dưới đây là một ví dụ chương trình đọc file theo từng dòng với BufferedReader:
package com.journaldev.readfileslinebyline;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFileLineByLineUsingBufferedReader {
public static void main(String[] args) {
BufferedReader reader;
try {
reader = new BufferedReader(new FileReader("sample.txt"));
String line = reader.readLine();
while (line != null) {
System.out.println(line);
// read next line
line = reader.readLine();
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Tiếp tục việc học của bạn với BufferedReader API Doc (Java SE 8).
Đọc file theo từng dòng bằng Scanner
Bạn có thể sử dụng lớp Scanner để mở một file và sau đó đọc nội dung của nó theo từng dòng.
Dưới đây là một chương trình ví dụ để đọc file theo từng dòng với Scanner:
package com.journaldev.readfileslinebyline;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class ReadFileLineByLineUsingScanner {
public static void main(String[] args) {
try {
Scanner scanner = new Scanner(new File("sample.txt"));
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
scanner.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
Tiếp tục việc học của bạn với ScannerAPI Doc (Java SE 8).
Đọc file theo từng dòng bằng Files
java.nio.file.Files là một lớp tiện ích chứa nhiều phương thức hữu ích. Phương thức readAllLines() có thể được dùng để đọc toàn bộ các dòng trong file vào một danh sách các chuỗi.
Dưới đây là một chương trình ví dụ để đọc file theo từng dòng với Files:
package com.journaldev.readfileslinebyline;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
public class ReadFileLineByLineUsingFiles {
public static void main(String[] args) {
try {
List<String> allLines = Files.readAllLines(Paths.get("sample.txt"));
for (String line : allLines) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Tiếp tục việc học của bạn với Files API Doc (Java SE 8).
Đọc file theo từng dòng bằng RandomAccessFile
Bạn có thể sử dụng RandomAccessFile để mở một file ở chế độ đọc và sau đó dùng phương thức readLine của nó để đọc file theo từng dòng.
Dưới đây là một chương trình ví dụ để đọc file theo từng dòng với RandomAccessFile:
package com.journaldev.readfileslinebyline;
import java.io.IOException;
import java.io.RandomAccessFile;
public class ReadFileLineByLineUsingRandomAccessFile {
public static void main(String[] args) {
try {
RandomAccessFile file = new RandomAccessFile("sample.txt", "r");
String str;
while ((str = file.readLine()) != null) {
System.out.println(str);
}
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Tiếp tục việc học của bạn với RandomAccessFile API Doc (Java SE 8).
Xử lý các loại Encoding khác nhau khi đọc file trong Java
Nếu một file được lưu trữ với encoding khác UTF-8, bạn nên chỉ định đúng encoding khi đọc file.
Đọc file với UTF-8 Encoding
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
public class ReadUTF8File {
public static void main(String[] args) {
try {
// This line reads the content of the file "example.txt" assuming it's encoded in UTF-8.
// The Path.of("example.txt") method creates a Path object representing the file path.
// The StandardCharsets.UTF_8 parameter specifies the character set to use for decoding.
String content = Files.readString(Path.of("example.txt"), StandardCharsets.UTF_8);
// This line prints the content of the file to the console.
System.out.println(content);
} catch (IOException e) {
// This block catches any IOException that might occur during file reading and prints the stack trace.
e.printStackTrace();
}
}
}
Đọc file với mã hóa UTF-16
import java.nio.charset.Charset;
import java.nio.file.*;
public class ReadUTF16File {
public static void main(String[] args) {
try {
// This line reads the content of the file "example.txt" assuming it's encoded in UTF-16.
// The Path.of("example.txt") method creates a Path object representing the file path.
// The Charset.forName("UTF-16") parameter specifies the character set to use for decoding.
String content = Files.readString(Path.of("example.txt"), Charset.forName("UTF-16"));
// This line prints the content of the file to the console.
System.out.println(content);
} catch (IOException e) {
// This block catches any IOException that might occur during file reading and prints the stack trace.
e.printStackTrace();
}
}
}
Xử lý hiệu quả các file dung lượng lớn bằng Streams hoặc FileChannel
Đối với các file có kích thước rất lớn (như log hoặc dataset tính bằng GB), NIO API của Java (FileChannel) là một lựa chọn hiệu năng cao thay thế cho cách đọc file thông thường.
Dưới đây là một ví dụ:
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.*;
public class FileChannelExample {
public static void main(String[] args) {
try (FileChannel fileChannel = FileChannel.open(Path.of("largefile.txt"), StandardOpenOption.READ)) {
// Allocate a ByteBuffer with a capacity of 4096 bytes to read data from the file channel.
ByteBuffer buffer = ByteBuffer.allocate(4096);
// Continuously read data from the file channel into the buffer until there is no more data to read.
while (fileChannel.read(buffer) > 0) {
// Flip the buffer to prepare it for reading. This sets the limit to the current position and the position to 0.
buffer.flip();
// Convert the buffer's content to a string and print it to the console. The parameters specify the start index, end index, and the character set.
System.out.print(new String(buffer.array(), 0, buffer.limit()));
// Clear the buffer to prepare it for the next read operation. This sets the position to 0 and the limit to the capacity.
buffer.clear();
}
} catch (IOException e) {
// Catch any IOException that might occur during file reading and print the stack trace.
e.printStackTrace();
}
}
}
Sử dụng FileChannel giúp giảm đáng kể mức sử dụng bộ nhớ so với việc nạp toàn bộ file vào bộ nhớ cùng lúc.
Để tìm hiểu thêm các kỹ thuật xử lý file nâng cao, bạn có thể tham khảo tutorial về Java Files – java.nio.file.Files Class.
FAQs
1. Làm thế nào để đọc file trong Java bằng FileReader?
Để đọc file trong Java bằng FileReader, bạn có thể tạo một instance của FileReader và đọc dữ liệu dạng ký tự từ file. Tuy nhiên, FileReader không phải là lựa chọn hiệu quả nhất vì nó không buffer dữ liệu đầu vào. Một cách tốt hơn là bọc nó trong BufferedReader.
import java.io.FileReader;
import java.io.IOException;
public class FileReaderExample {
public static void main(String[] args) {
try (FileReader reader = new FileReader("example.txt")) {
int data;
while ((data = reader.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Để đọc file hiệu quả hơn, bạn nên sử dụng BufferedReader.
2. Làm thế nào để đọc file theo từng dòng trong Java?
Cách phổ biến nhất để đọc file theo từng dòng trong Java là sử dụng BufferedReader. Phương pháp này tiết kiệm bộ nhớ và hoạt động tốt ngay cả với các file lớn.
Ví dụ sử dụng BufferedReader:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadFileLineByLine {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Để tìm hiểu thêm các phương thức xử lý file khác, bạn có thể tham khảo tutorial về Java File Handling.
3. Cách hiệu quả nhất để đọc file lớn trong Java là gì?
Khi làm việc với các file có kích thước lớn, việc nạp toàn bộ file vào bộ nhớ là không hiệu quả. Thay vào đó, bạn nên sử dụng streams hoặc Java NIO (Non-blocking I/O) như FileChannel để đạt hiệu năng tốt hơn.
Ví dụ sử dụng BufferedReader với Streams (hiệu quả cho file lớn):
import java.io.*;
import java.nio.file.*;
public class LargeFileReader {
public static void main(String[] args) {
try (BufferedReader reader = Files.newBufferedReader(Path.of("largefile.txt"))) {
reader.lines().forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Sử dụng FileChannel (Tốt nhất cho các file cực lớn)
Đối với những file có kích thước cực lớn, bạn nên cân nhắc dùng memory-mapped files hoặc FileChannel để cải thiện hiệu năng, như đã mô tả trong phần trên.
4. Làm thế nào để xử lý lỗi khi đọc file trong Java?
Việc xử lý lỗi là rất quan trọng để tránh chương trình bị crash do các vấn đề như: file không tồn tại, lỗi quyền truy cập, hoặc sai lệch encoding.
- Sử dụng try-with-resources để tự động đóng tài nguyên file.
- Kiểm tra sự tồn tại của file bằng
Files.exists(Path.of("file.txt")). - Bắt các exception như
IOExceptionđể xử lý lỗi một cách an toàn.
import java.io.*;
public class FileErrorHandling {
public static void main(String[] args) {
File file = new File("nonexistent.txt");
if (!file.exists()) {
System.out.println("File does not exist!");
return;
}
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
System.out.println(reader.readLine());
} catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
}
}
}
5. Sự khác biệt giữa FileReader và BufferedReader là gì?
| Đặc điểm | FileReader | BufferedReader |
|---|---|---|
| Hiệu năng | Đọc từng ký tự một | Đọc theo từng buffer đầy (mặc định 8192 bytes) |
| Trường hợp sử dụng | File nhỏ, đọc ký tự đơn giản | Đọc hiệu quả, phù hợp với file lớn |
| Mức độ hiệu quả | Kém hiệu quả | Rất hiệu quả |
Để xử lý các file văn bản lớn một cách hiệu quả, bạn nên ưu tiên dùng BufferedReader thay vì FileReader.
Kết luận
Trong hướng dẫn toàn diện này, bạn đã tìm hiểu cách đọc file trong Java với nhiều phương pháp, bao gồm việc sử dụng BufferedReader, Scanner, Files.readAllLines(), và RandomAccessFile. Bạn cũng đã học cách xử lý lỗi khi đọc file, sự khác biệt giữa FileReader và BufferedReader, cũng như cách xử lý hiệu quả các file lớn bằng FileChannel hoặc memory-mapped files.