openplanning

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

Xem thêm các chuyên mục:

Nhóm phát triển của chúng tôi vừa ra mắt website langlearning.net học tiếng Anh, Nga, Đức, Pháp, Việt, Trung, Hàn, Nhật, ... miễn phí cho tất cả mọi người.
Là một website được viết trên công nghệ web Flutter vì vậy hỗ trợ rất tốt cho người học, kể cả những người học khó tính nhất.
Hiện tại website đang tiếp tục được cập nhập nội dung cho phong phú và đầy đủ hơn. Mong các bạn nghé thăm và ủng hộ website mới của chúng tôi.
Hãy theo dõi chúng tôi trên Fanpage để nhận được thông báo mỗi khi có bài viết mới. Facebook

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ó.

Xem thêm các chuyên mục: