Java 转换流的简单理解

字符编码和字符集

字符编码

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。按照某种规则,将字符存储到计算机中,称为编码。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。

编码:字符 --> 字节

解码:字节 --> 字符

  • 字符编码,是一套自然语言的字符与二进制数之间的对应规则。

字符集

  • 字符集,也叫编码表,是一个系统支持的所有字符集合,包括国家文字、标点符号、图形符号、数字等。

计算机要准确的存储和识別各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。

编码引出的问题

在IDEA中,使用FileReader读取项目中的文本文件。由于IDEA的设置,都是默认的UTF-8编码,所以没有任何问题。但是,当读取系统中创建的文本文件时,由于系统的默认是GBK编码,就会出现乱码。

那么该如何解决呢?我们可以使用InputStreamReader类、OutputStreamWriter类,指定编码来进行读写操作,这时候就不会出现乱码的情况了。

OutputStreamWriter类

java.io.OutputStreamWriter是字符流通向字节流的桥梁:可使用指定的charset将要写入流中的字符编码成字节(编码)。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

OutputStreamWriter类是java.io.Writer的子类,所以可以使用父类方法:

public void write(int c)
// 写入单个字符。

public void write(char cbuf[])
// 写入字符数组。

abstract public void write(char cbuf[], int off, int len)
// 写入字符数组的某一部分,off是数组的开始索引,len是写的字符个数。

public void write(String str)
// 写入字符串。

public void write(String str, int off, int len)
//写入字符的某一部分。off是字符的开始素,len是写的字符个数。

abstract public void flush()
// 刷新该流的缓冲。

abstract public void close()
// 关闭此流,但会先刷新它。

构造方法

OutputStreamWriter(OutputStream out)
// 创建使用默认编码的OutputStreamWriter对象

OutputStreamWriter(OutputStream out, String charsetName)
// 创建使用指定编码的OutputStreamWriter对象
参数:
OutputStreamWriter out:字节输出流
String charsetName:指定编码表的名称,不区分大小写。如utf-8/UTF-8。

使用步骤:

1.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的編码表名称。
2.使用OutputStreamWriter对象中的方法write,把字符转换为字节存储到缓冲区中(编码)。
3.使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)。
4.释放资源。

举例:指定编码,将数据保存到文件中。

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class DemoOutputStreamWriter {
    public static void main(String[] args) throws IOException {
        Gbk_TXT();
    }

    private static void Gbk_TXT() throws IOException {
        // 创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的編码表名称。指定编码为GBK。
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/OutputStreamWriter.txt"), "gbk");

        // 使用OutputStreamWriter对象中的方法write,把字符转换为字节存储到缓冲区中(编码)。
        for (int i = 0; i < 5; i++) {
            osw.write("你好!" + i);
            osw.write("\n");
        }

        // 使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)。
        osw.flush();

        // 释放资源。
        osw.close();
    }
}

运行,生成一个OutputStreamWriter.txt文件,文件内容如下:

img

由于IDEA默认编码是UTF-8,这里使用了GBK编码格式写入数据进文件,所以在IDEA里面查看文件的内容出现乱码。

InputStreamReader类

java.io.InputStreamReader是字节流通向字符流的桥梁:它使用指定的charset读取字节并将其解码为字符(解码)。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

InputStreamReader类是java.io.Reader的子类,所以可以使用父类方法:

public void close()
// 关闭此流并释放与此流相关联的任何系统资源。

public int read()
// 从输入流读取一个字符。

public int read(char[] chars)
// 从输入流中读取一些字符,并将它们存储到字符数组chars中。

构造方法

InputStreamReader(InputStream in)
// 创建默认字符集的InputStreamReader对象

InputStreamReader(InputStream in, String charsetName)
// 创建指定字符集的InputStreamReader对象
参数:
InputStream in:字符输入流
String charsetName:指定编码表的名称,不区分大小写。如gbk/GBK。

使用步骤:

1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称。
2.使用InputStreamReader对象中的方法read,读取文件。
3.释放资源。

注意事项:构造方法中指定的编码表名称要和文件的编码相同,否则会发生乱码。

举例:按指定解码格式,读取OutputStreamWriter.txt文件的内容

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class DemoInputStreamReader {
    public static void main(String[] args) throws IOException {
        decode_GBK();
    }

    private static void decode_GBK() throws IOException {
        // 创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称。
        InputStreamReader isr = new InputStreamReader(new FileInputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/OutputStreamWriter.txt"), "GBK");

        // 使用InputStreamReader对象中的方法read,读取文件。
        char[] chars = new char[25];
        while ((isr.read(chars)) != -1) {
            System.out.println(chars);
        }

        // 释放资源。
        isr.close();
    }
}

控制台输出:

你好!0
你好!1
你好!2
你好!3
你好!4

练习:转换文件编码

将编码GBK编码的文件文本,转换为UTF-8编码的文件文本。

分析:

1.创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称GBK。
2.创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称UTF-8。
3.使用InputStreamReader对象中的方法read,读取文件。
4.使用OutputStreamWriter对象中的方法write,把读取的数据写入到文件中。
5.释放资源。

GBK.txt文件内容如下:

img

代码实现:

import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class DemoInOutAndReaderWriter {
    public static void main(String[] args) throws IOException {
        method();
    }

    private static void method() throws IOException {
        // 创建InputStreamReader对象,构造方法中传递字节输入流和指定的编码表名称GBK。
        InputStreamReader isr = new InputStreamReader(new FileInputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/GBK.txt"), "GBK");

        // 创建OutputStreamWriter对象,构造方法中传递字节输出流和指定的编码表名称UTF-8。
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("/Users/liyihua/IdeaProjects/Study/src/view/study/demo35/UTF_8.txt"), "UTF-8");

        // 使用InputStreamReader对象中的方法read,读取文件。
        int len = 0;
        while ((len = isr.read()) != -1) {
            osw.write(len);
        }

        // 释放资源。
        isr.close();
        osw.close();
    }
}

运行生成一个UTF_8.txt文件,文件内容如下:

img

posted @ 2020-02-07 01:12  LeeHua  阅读(1752)  评论(0编辑  收藏  举报