openplanning

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

  1. InputStreamReader
  2. UTF-16 InputStreamReader
  3. UTF-8 InputStreamReader

1. InputStreamReader

InputStreamReader là một lớp con của Reader, nó là một cầu nối cho phép bạn chuyển một byte stream thành một character stream, hay nói cách khác nó cho phép bạn chuyển đổi một InputStream thành một Reader.
Mẹo: Để chuyển một "InputStream" thành một "Reader" bạn chỉ cần nối 2 từ này với nhau để thành từ "InputStreamReader" bạn sẽ có được lời giải của vấn đề.
InputStreamReader​ constructors
InputStreamReader​(InputStream in)    

InputStreamReader​(InputStream in, String charsetName)    

InputStreamReader​(InputStream in, Charset cs)    

InputStreamReader​(InputStream in, CharsetDecoder dec)

2. UTF-16 InputStreamReader

UTF-16 là một mã hoá (encoding) khá phổ biến đối với văn bản tiếng Trung Quốc hoặc tiếng Nhật. Trong ví dụ này chúng ta sẽ phân tích làm thế nào InputStreamReader đọc được các văn bản UTF-16.
Trước hết, hãy xem file văn bản tiếng Nhật dưới đây, nó được mã hoá UTF-16:
utf16-file-with-bom.txt
JP日本-八洲
Code đầy đủ của ví dụ:
InputStreamReader_UTF16_Ex1.java
package org.o7planning.inputstreamreader.ex;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

public class InputStreamReader_UTF16_Ex1 {

    // A file in UTF-16.
    private static final String fileURL = "https://s3.o7planning.com/txt/utf16-file-with-bom.txt";
    
    public static void main(String[] args) throws MalformedURLException, IOException {
        System.out.println(" --- Characters in Character Stream (InputStreamReader) ---");
        readAs_UTF16_Character_Stream();

        System.out.println();
        System.out.println(" --- Bytes in UTF-16 file ---");
        readAs_Binary_Stream();
    }

    private static void readAs_UTF16_Character_Stream() throws MalformedURLException, IOException {

        InputStream is = new URL(fileURL).openStream();
        InputStreamReader isr = new InputStreamReader(is, "UTF-16");

        int charCode;
        while ((charCode = isr.read()) != -1) { // Read each character.
            System.out.println((char) charCode + "  " + charCode);
        }
        isr.close();
    }

    private static void readAs_Binary_Stream() throws MalformedURLException, IOException {

        InputStream is = new URL(fileURL).openStream();

        int byteValue;
        while ((byteValue = is.read()) != -1) { // Read each byte.
            System.out.println((char) byteValue + "  " + byteValue);
        }
        is.close();
    }
}
Output:
--- Characters in Character Stream (InputStreamReader) ---
J  74
P  80
日  26085
本  26412
-  45
八  20843
洲  27954

 --- Bytes in UTF-16 file ---
þ  254
ÿ  255
  0
J  74
  0
P  80
e  101
å  229
g  103
,  44
  0
-  45
Q  81
k  107
m  109
2  50
Tạo ra một đối tượng InputStreamReader với mã hoá UTF-16 và bao bọc một đối tượng InputStream:
String url = "https://s3.o7planning.com/txt/utf16-file-with-bom.txt";

InputStream is = new URL(url).openStream();
InputStreamReader isr = new InputStreamReader(is, "UTF-16");
Hình ảnh dưới đây cho thấy các bytes trong file UTF-16. Hai bytes đầu tiên (254, 255) được sử dụng để đánh dấu rằng nó bắt đầu của một văn bản UTF-16.
UTF-16 InputStreamReader đọc 2 bytes đầu tiên để xác định kiểu mã hoá của văn bản, và biết rằng nó đang làm việc với một văn bản UTF-16. Nó ghép 2 bytes liên tiếp để tạo thành một ký tự...

3. UTF-8 InputStreamReader

UTF-8 là một mã hoá (encoding) phổ biến nhất thế giới, nó có thể mã hoá mọi chữ viết trên thế giới bao gồm cả ký tự của Trung Quốc và ký tự của Nhật Bản. Bây giờ chúng ta sẽ phân tích làm thế nào InputStreamReader đọc được các văn bản UTF-8.
Trước hết, hãy xem file văn bản tiếng Nhật dưới đây, nó được mã hoá UTF-8:
utf8-file-without-bom.txt
JP日本-八洲
Code đầy đủ của ví dụ:
InputStreamReader_UTF8_Ex1.java
package org.o7planning.inputstreamreader.ex;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;

public class InputStreamReader_UTF8_Ex1 {

    // A file with UTF-8 encoding (And without BOM (Byte Order Mark)).
    private static final String fileURL = "https://s3.o7planning.com/txt/utf8-file-without-bom.txt";
    
    public static void main(String[] args) throws MalformedURLException, IOException {
        System.out.println(" --- Characters in Character Stream (InputStreamReader) ---");
        readAs_UTF8_Character_Stream();

        System.out.println();
        System.out.println(" --- Bytes in UTF-8 file ---");
        readAs_Binary_Stream();
    }

    private static void readAs_UTF8_Character_Stream() throws MalformedURLException, IOException {
        
        InputStream is = new URL(fileURL).openStream();
        InputStreamReader isr = new InputStreamReader(is, "UTF-8");

        int charCode;
        while ((charCode = isr.read()) != -1) { // Read each character.
            System.out.println((char) charCode + "  " + charCode);
        }
        isr.close();
    }

    private static void readAs_Binary_Stream() throws MalformedURLException, IOException {

        InputStream is = new URL(fileURL).openStream();

        int byteValue;
        while ((byteValue = is.read()) != -1) { // Read each byte.
            System.out.println((char) byteValue + "  " + byteValue);
        }
        is.close();
    }
}
Output:
--- Characters in Character Stream (InputStreamReader) ---
J  74
P  80
日  26085
本  26412
-  45
八  20843
洲  27954

 --- Bytes in UTF-8 file ---
J  74
P  80
æ  230
—  151
¥  165
æ  230
œ  156
¬  172
-  45
å  229
…  133
«  171
æ  230
´  180
²  178
Tạo ra một đối tượng InputStreamReader với mã hoá UTF-8 và bao bọc một đối tượng InputStream:
String url = "https://s3.o7planning.com/txt/utf8-file-without-bom.txt";

InputStream is = new URL(url).openStream();
InputStreamReader isr = new InputStreamReader(is, "UTF-8");
Hình ảnh dưới đây cho thấy các bytes trong file UTF-8:
Mã hoá UTF-8 phức tạp hơn rất nhiều so với UTF-16, nó cần 1, 2, 3 hoặc 4 bytes để lưu trữ một ký tự, điều này phụ thuộc vào mã của ký tự.
Number of bytes
From
To
Byte 1
Byte 2
Byte 3
Byte 4
1
U+0000
0
U+007F
127
0xxxxxxx
2
U+0080
128
U+07FF
2047
110xxxxx
10xxxxxx
3
U+0800
2048
U+FFFF
65535
1110xxxx
10xxxxxx
10xxxxxx
4
U+10000
65536
U+10FFFF
1114111
11110xxx
10xxxxxx
10xxxxxx
10xxxxxx
Hình ảnh dưới đây là một ví dụ cho thấy cách UTF-8 InputStreamReader biến 3 bytes của UTF-8 thành 1 ký tự 2 bytes của Java:

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

Show More