openplanning

Hướng dẫn và ví dụ Java FileReader

  1. FileReader
  2. Examples
  3. Vấn đề UTF-8 BOM!

1. FileReader

FileReader là một lớp con của InputStreamReader, nó được sử dụng để đọc các file văn bản.
FileReader không có thêm các phương thức nào ngoài các phương thức được thừa kế từ InputStreamReader, thực tế bạn có thể sử dụng InputStreamReader để đọc các ký tự từ bất kỳ một nguồn nào, tuy nhiên FileReader được thiết kế riêng để đọc các ký tự từ file hệ thống.
FileReader​ constructors
FileReader​(File file)    

FileReader​(FileDescriptor fd)    

FileReader​(File file, Charset charset)    

FileReader​(String fileName)    

FileReader​(String fileName, Charset charset)
Chú ý: Các constructor có tham số Charset được thêm vào FileReader từ phiên bản Java 11, vì vậy nếu bạn đang sử dụng Java phiên bản cũ hơn và muốn đọc một file với mã hoá (encoding) được chỉ định hãy sử dụng lớp InputStreamReader để thay thế.

2. Examples

Ví dụ đọc một file văn bản:
file-test.txt
File Content
FileReaderEx1.java
package org.o7planning.filereader.ex;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;

public class FileReaderEx1 {

    public static void main(String[] args) throws MalformedURLException, IOException {
        File file = new File("file-test.txt");
 
        FileReader fis = new FileReader(file);
        
        int charCode;
        while((charCode = fis.read()) != -1) {
            System.out.println((char)charCode + "  " + charCode);
        }
        fis.close();
    }
}
Output:
F  70
i  105
l  108
e  101
   32
C  67
o  111
n  110
t  116
e  101
n  110
t  116
Khi đọc một file văn bản bạn nên sử dụng kết hợp BufferedReaderFileReader để có được hiệu xuất tốt nhất:
students.txt
# Students:

John P
Sarah M
# Sarah B
Charles B
Mary T
Sophia B
FileReaderEx2.java
package org.o7planning.filereader.ex;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.net.MalformedURLException;

public class FileReaderEx2 {

    public static void main(String[] args) throws MalformedURLException, IOException {
        File file = new File("students.txt");
 
        Reader reader = new FileReader(file);
        BufferedReader br = new BufferedReader(reader);
        
        String line;
        while((line = br.readLine()) != null) {
            System.out.println(line);
        }
        br.close();
    }
}
Output:
# Students:

John P
Sarah M
# Sarah B
Charles B
Mary T
Sophia B
Ví dụ: Đọc một file văn bản và in ra các dòng văn bản không bắt đầu bởi ký tự '#' (Dòng chú thích):
FileReaderEx3.java
package org.o7planning.filereader.ex;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.net.MalformedURLException;

public class FileReaderEx3 {

    public static void main(String[] args) throws MalformedURLException, IOException {
        File file = new File("students.txt");
 
        Reader reader = new FileReader(file);
        BufferedReader br = new BufferedReader(reader);
        
        br.lines() // java.util.stream.Stream
           .filter(line -> !line.startsWith("#")) // Not starts with "#".
           .forEach(System.out::println);
        
        br.close();
    }
}
Output:
John P
Sarah M
Charles B
Mary T
Sophia B

3. Vấn đề UTF-8 BOM!

Trước khi UTF-8 trở lên phổ biến các công cụ tạo ra file UTF-8 luôn thêm vào 3 bytes đầu tiên để đánh dấu rằng đây là file được mã hoá UTF-8, chúng thường được gọi là BOM (Byte Order Mark). Trong khi các file UTF-8 được tạo ra bởi Java không bao gồm BOM.
FileReader không tự động loại bỏ BOM khi đọc các file UTF-8. Đội ngũ thiết kế Java hiểu được điều này tuy nhiên không có một bản cập nhập nào được thực hiện vì nó sẽ phá vỡ các thư viện của bên thứ ba viết trên Java trước đó như XML Parser, ...
Chẳng hạn, dưới đây là một file UTF-8 (BOM) được tạo bởi một công cụ cũ, bạn có thể download nó để test vấn đề đang được thảo luận:
utf8-file-with-bom-test.txt
Hello
Và sử dụng FileReader để đọc file nói trên:
FileReader_Utf8_BOM.java
package org.o7planning.filereader.ex;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.nio.charset.StandardCharsets;

public class FileReader_Utf8_BOM {

    public static void main(String[] args) throws MalformedURLException, IOException {
        File file = new File("utf8-file-with-bom-test.txt");  
        
        System.out.println("--- Read by FileReader ---");
        readByFileReader(file);
        
        System.out.println("--- Read by InputStreamReader ---");
        readByInputStreamReader(file);
    }

    private static void readByFileReader(File file) throws IOException {
        FileReader fr = new FileReader(file, StandardCharsets.UTF_8);

        int charCode;
        while ((charCode = fr.read()) != -1) {
            System.out.println((char) charCode + "  " + charCode);
        }
        fr.close();
    }
    
    private static void readByInputStreamReader(File file) throws IOException {
        InputStream is = new FileInputStream(file);

        InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);

        int charCode;
        while ((charCode = isr.read()) != -1) {
            System.out.println((char) charCode + "  " + charCode);
        }
        isr.close();
    }
}
Output:
--- Read by FileReader ---
  65279
H  72
e  101
l  108
l  108
o  111
--- Read by InputStreamReader ---
  65279
H  72
e  101
l  108
l  108
o  111
Ký tự với mã 65279 xuất hiện trong kết quả, nó là một ký tự không mong muốn.
Một vài lớp dưới đây hỗ trợ loại bỏ BOM bạn có thể cân nhắc sử dụng:
BOMInputStream
BOMInputStream là một lớp trong thư viện Apache Commons IO hỗ trợ loại bỏ BOM.
Maven dependency
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.8.0</version>
</dependency>
BOMInputStreamEx1.java
package org.o7planning.filereader.ex;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

import org.apache.commons.io.input.BOMInputStream;

public class BOMInputStreamEx1 {

    public static void main(String[] args) throws IOException {
        File file = new File("utf8-file-with-bom-test.txt");
        FileInputStream fis = new FileInputStream(file);

        BOMInputStream bis = new BOMInputStream(fis);

        InputStreamReader isr = new InputStreamReader(bis, StandardCharsets.UTF_8);

        int charCode;
        while ((charCode = isr.read()) != -1) {
            System.out.println((char) charCode + "  " + charCode);
        }
        isr.close();
    }
}
Output:
H  72
e  101
l  108
l  108
o  111
UnicodeReader
UnicodeReader là một lớp nằm trong thư viện "Google Data Java Client Library" hỗ trợ loại bỏ BOM.
Maven dependency
<!-- https://mvnrepository.com/artifact/com.google.gdata/core -->
<dependency>
    <groupId>com.google.gdata</groupId>
    <artifactId>core</artifactId>
    <version>1.47.1</version>
</dependency>
UnicodeReaderEx1.java
package org.o7planning.filereader.ex;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import com.google.gdata.util.io.base.UnicodeReader;

public class UnicodeReaderEx1 {

    public static void main(String[] args) throws IOException {
        File file = new File("utf8-file-with-bom-test.txt");
        FileInputStream fis = new FileInputStream(file);
        
        UnicodeReader isr = new UnicodeReader(fis, "UTF-8");

        int charCode;
        while ((charCode = isr.read()) != -1) {
            System.out.println((char) charCode + "  " + charCode);
        }
        isr.close();
    }  
}
Output:
H  72
e  101
l  108
l  108
o  111

Các hướng dẫn Java IO

Show More