zoukankan      html  css  js  c++  java
  • 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("
    ");
            }
    
            // 使用OutputStreamWriter对象中的方法flush,把内存缓冲区中的字节刷新到文件中(使用字节流写字节的过程)。
            osw.flush();
    
            // 释放资源。
            osw.close();
        }
    }

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

     由于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-83.使用InputStreamReader对象中的方法read,读取文件。
    4.使用OutputStreamWriter对象中的方法write,把读取的数据写入到文件中。
    5.释放资源。

    GBK.txt文件内容如下:

    代码实现:

    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文件,文件内容如下:

              

  • 相关阅读:
    Linux ,Ubuntu 分区建议大小
    [No000019A]【波浪理论精典教学课程】
    CS(计算机科学)知识体
    如何量化考核技术人的KPI?
    Linux系统的命令应该如何记?
    数学和物理太难?这些 GIF 让你秒懂抽象概念
    加密数字货币的 7 个致命悖论
    量子力学中,全体自然数之和是负十二分之一,物理意义是什么?
    30岁左右的人,来谈谈你犯了哪些错误?
    一篇文章学懂Shell脚本,最简明的教程在这里
  • 原文地址:https://www.cnblogs.com/liyihua/p/12271721.html
Copyright © 2011-2022 走看看