IO流——字符集

一、IO流的体系

1.1 字符集

1.1.1 计算机的存储规则

① ASCII字符集

ASCII码对应的最大数字是127,一共是0-127,128个字符。一个字节最多可以表示256的数据。所以可以得出一个结论:存储英文,一个字节足以。

编码:把字符集当中查询到的数据,按照一定的规则进行计算,变成真实的能存储在硬盘当中的二进制数据。解码就是相反的过程。

② GBK字符集

底层如何区分中英文:

③ Unicode字符集

不管是一个字母还是别的字符,UTF-16统一用16个bit,而UTF-32是用32个bit。这在某些字符的存储上十分浪费空间。

后来出现的UTF-8就采用了分门处理的方式进行了优化。

1.2.1 为什么会有乱码?

只读取了片段,解码成不符合字符集规则的数据出现乱码。

原因二:编码和解码的方式不一致。

因为拷贝的时候,数据源的数据没有丢失,拷贝的一样,而且目的地编码方式跟数据源保持一致就不会出现乱码。

1.3.1 Java中编码和解码的代码实现

java 复制代码
package com.lkbhua.IO;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Arrays;

public class demo {
    public static void main(String[] args) throws UnsupportedEncodingException {
        /*  Java中编码的方式:
                public byte[] getBytes()                        使用默认方式进行编码
                public byte[] getBytes(String charsetName)      使用指定方式进行编码

            Java中解码的方式:
                String(byte[] bytes)                            使用默认方式进行解码
                String(byte[] bytes, String charsetName)        使用指定方式进行解码
         */

        // 1、编码
        String str = "Ai中国";
        byte[] bytes = str.getBytes(); // GBK E: 1 C: 2
        System.out.println(Arrays.toString(bytes));
        // [65, 105, -42, -48, -71, -6]

        // 2、指定编码
        byte[] bytes1 = str.getBytes("UTF-8");
        System.out.println(Arrays.toString(bytes1));
        // [65, 105, -28, -72, -83, -27, -101, -67]

        // 3、解码
        String str1 = new String(bytes);
        System.out.println(str1);
        // Ai中国

        // 4、指定解码
        String str2 = new String(bytes1, "UTF-8");
        System.out.println(str2);
        // Ai中国
    }
}

1.2 字符流

对于原因二:编码和解码方式不统一的情况我们可以通过统一编码方式进行很好的解决。但是原因一怎么解决呢?字符流可以很好的解决。

1.2.1 FileReader字符输入流

空参的read()方法:

java 复制代码
package com.lkbhua.IO.FileReaderDemo;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class demo1 {
    public static void main(String[] args) throws IOException {
        /*
            第一步: 创建对象
            public FileReader(File file)            创建字符输入流关联本地文件
            public FileReader(String fileName)      创建字符输入流关联本地文件

            第二步: 读取数据
            public int read()                       读取数据,读到末尾返回-1
            public int read(char[] cbuf)            读取多个数据,读到末尾返回-1

            第三步: 释放资源
            public void close()                    释放资源
        */

        // 1、创建对象并关联本地文件
        FileReader fr = new FileReader("lkb04-File&IOCode\\a.txt");
        // 2、读取数据 read()
        // 细节1: 默认是一个字节一个字节读取,如果遇见中文就会读取多个(GBK:2,UTF-8:3)
        // 细节2: 在读取之后,方法底层还会解码转成十进制。
        //       最终将这个十进制作为返回值
        //       这个十进制的数据也表示在字符集上的数字
        // 比如是English: 0110 0001
        //      read方法读取进行解码: 97
        // 比如是Chinese: 1100 1001 1000 1001
        //      read方法读取进行解码: 20989
        int ch;
        while((ch = fr.read()) != -1){
            System.out.print((char)ch);
        }
        // 3、释放资源
        fr.close();
    }
}

带参的read()方法:

java 复制代码
package com.lkbhua.IO.FileReaderDemo;

import java.io.FileReader;
import java.io.IOException;

public class demo2 {
    public static void main(String[] args) throws IOException {
        /*
            第一步: 创建对象
            public FileReader(File file)            创建字符输入流关联本地文件
            public FileReader(String fileName)      创建字符输入流关联本地文件

            第二步: 读取数据
            public int read()                       读取数据,读到末尾返回-1
            public int read(char[] cbuf)            读取多个数据,读到末尾返回-1

            第三步: 释放资源
            public void close()                    释放资源
        */

        // 1、创建对象
        FileReader fr = new FileReader("lkb04-File&IOCode\\a.txt");
        // 2、读取数据
        // read(chars): 读取数据、解码、强壮三步合并了,把强转之后的字符放到数组当中
        // 空参的read + 强转类型转换
        char[] chars = new char[2];
        int len;
        while ((len = fr.read(chars)) != -1){
            // 把数据中的字符串进行打印
            System.out.print(new String(chars, 0, len));
        }
        // 3、释放资源
        fr.close();
    }
}

1.2.2 FileWrtie字符输出流

相关推荐
_小马快跑_39 分钟前
Java 的 8 大基本数据类型:为何是不可或缺的设计?
java
Re_zero3 小时前
线上日志被清空?这段仅10行的 IO 代码里竟然藏着3个毒瘤
java·后端
洋洋技术笔记3 小时前
Spring Boot条件注解详解
java·spring boot
程序员清风21 小时前
程序员兼职必看:靠谱软件外包平台挑选指南与避坑清单!
java·后端·面试
皮皮林5511 天前
利用闲置 Mac 从零部署 OpenClaw 教程 !
java
华仔啊1 天前
挖到了 1 个 Java 小特性:var,用完就回不去了
java·后端
SimonKing1 天前
SpringBoot整合秘笈:让Mybatis用上Calcite,实现统一SQL查询
java·后端·程序员
日月云棠2 天前
各版本JDK对比:JDK 25 特性详解
java
用户8307196840822 天前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
JavaGuide2 天前
Claude Opus 4.6 真的用不起了!我换成了国产 M2.5,实测真香!!
java·spring·ai·claude code