openplanning

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

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

1. OutputStreamWriter

OutputStreamWriter là một lớp con của Writer, 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 OutputStream thành một Writer
Mẹo: Để chuyển một "OutputStream" thành một "Writer" bạn chỉ cần nối 2 từ này với nhau để thành từ "OutputStreamWriter" bạn sẽ có được lời giải của vấn đề.
OutputStreamWriter​ constructors
OutputStreamWriter​(OutputStream out)     

OutputStreamWriter​(OutputStream out, String charsetName)     
 
OutputStreamWriter​(OutputStream out, Charset cs)     

OutputStreamWriter​(OutputStream out, CharsetEncoder enc)
Ngoài các phương thức được thừa kế từ lớp cha, OutputStreamWriter có một vài phương thức của riêng nó.
Method
Description
String getEncoding()
Trả về tên của mã hóa ký tự đang được sử dụng bởi OutputStreamWriter.

2. UTF-16 OutputStreamWriter

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 để ghi một file với mã hoá UTF-16.
Và đây là nội dung cần ghi vào file:
JP日本-八洲
Trong ví dụ này chúng ta sử dụng UTF-16 OutputStreamWriter để ghi các ký tự vào một file, sau đó sử dụng FileInputStream để đọc từng byte dữ liệu của file đó.
OutputStreamWriter_UTF16_Ex1.java
package org.o7planning.outputstreamwriter.ex;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;

public class OutputStreamWriter_UTF16_Ex1 {

    private static final String filePath = "/Volumes/Data/test/utf16-file-out.txt";
    
    public static void main(String[] args) throws IOException {
        System.out.println(" --- Write UTF-16 File --- ");
        write_UTF16_Character_Stream();
        
        System.out.println(" --- Read File as Binary Stream --- ");
        readAs_Binary_Stream();
    }

    private static void write_UTF16_Character_Stream() throws IOException   {
        File outFile = new File(filePath);
        outFile.getParentFile().mkdirs(); // Create parent folder.

        // Create OutputStream to write a file.
        OutputStream os = new FileOutputStream(outFile);

        // Create a OutputStreamWriter  
        OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_16);

        String s = "JP日本-八洲";
        osw.write(s);
        osw.close();
    }

    private static void readAs_Binary_Stream() throws IOException {
        InputStream is = new FileInputStream(filePath);

        int byteValue;
        while ((byteValue = is.read()) != -1) { // Read byte by byte.
            System.out.println((char) byteValue + "  " + byteValue);
        }
        is.close();
    }
}
Output:
--- Write UTF-16 File ---
 --- Read File as Binary Stream ---
þ  254
ÿ  255
  0
J  74
  0
P  80
e  101
å  229
g  103
,  44
  0
-  45
Q  81
k  107
m  109
2  50
Trong Java, kiểu dữ liệu char có kích thước 2 bytes, và UTF-16 được sử dụng để mã hoá kiểu String. Hình ảnh dưới đây cho thấy các ký tự trên OutputStreamWriter:
Phân tích các bytes trên file vừa được tạo ra cho thấy: 2 bytes đầu tiên là (254, 255) được sử dụng để đánh dấu rằng đây là một văn bản được mã hoá UTF-16, chúng còn được gọi là BOM (Byte Order Mark), còn các bytes tiếp theo giống với các bytes trên OutputStreamWriter.

3. UTF-8 OutputStreamWriter

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ắt đầu từ Java5, UTF-8 là mã hoá mặc định khi đọc và ghi file.
Các file UTF-8 được tạo ra bởi Java sẽ không có BOM (Byte Order Mark) (Các bytes đầu tiên của file để đánh dấu rằng đây là một file UTF-8).
OutputStreamWriter_UTF8_Ex1.java
package org.o7planning.outputstreamwriter.ex;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;

public class OutputStreamWriter_UTF8_Ex1 {

    private static final String filePath = "/Volumes/Data/test/utf8-file-out.txt";
    
    public static void main(String[] args) throws IOException {
        System.out.println(" --- Write UTF-8 File --- ");
        write_UTF8_Character_Stream();
        
        System.out.println(" --- Read File as Binary Stream --- ");
        readAs_Binary_Stream();
    }

    private static void write_UTF8_Character_Stream() throws IOException   {
        File outFile = new File(filePath);
        outFile.getParentFile().mkdirs(); // Create parent folder.

        // Create OutputStream to write a file.
        OutputStream os = new FileOutputStream(outFile);

        // Create a OutputStreamWriter  
        OutputStreamWriter osw = new OutputStreamWriter(os, StandardCharsets.UTF_8);

        String s = "JP日本-八洲";
        osw.write(s);
        osw.close();
    }

    private static void readAs_Binary_Stream() throws IOException {
        InputStream is = new FileInputStream(filePath);

        int byteValue;
        while ((byteValue = is.read()) != -1) { // Read byte by byte.
            System.out.println((char) byteValue + "  " + byteValue);
        }
        is.close();
    }
}
Output:
--- Write UTF-8 File ---
 --- Read File as Binary Stream ---
J  74
P  80
æ  230
—  151
¥  165
æ  230
œ  156
¬  172
-  45
å  229
…  133
«  171
æ  230
´  180
²  178
Trong Java, kiểu dữ liệu char có kích thước 2 bytes, và UTF-16 được sử dụng để mã hoá kiểu String. Hình ảnh dưới đây cho thấy các ký tự trên OutputStreamWriter:
UTF-8 được mã hoá phức tạp hơn khá nhiều so với UTF-16, nó sử dụng 1, 2, 3 hoặc 4 bytes để lưu trữ một ký tự. Phân tích chi tiết các bytes trên file UTF-8 vừa được tạo ra cho thấy rõ điều đó.
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
Ví dụ ký tự "日" có mã số là 26085 thuộc phạm vi [2048,65535], UTF-8 sẽ cần 3 bytes để lưu trữ nó.

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

Show More