IO流(3)转换流、序列化流、打印流、Properties属性类

一、转换流

转换流的学习,先要了解字符编码

在这里插入图片描述

1. 字符编码与解码

  • 编码:把字符(字母、英文、标点符号、中文)等字符按照某种规则转换为二进制数据(字节数据)存储在计算机中

  • 解码:将存储在计算机中的二进制数据按照某种规则解码显示出来

  • 乱码原因:用规则A编码,也一定要用规则A解码,如果用规则B解码则会出现乱码

  • 解码:String(byte[] bytes, String charsetName):通过指定的字符集解码字节数组

  • 编码:byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码为字节数组

使用示例

public class Charset_Demo01 {
    public static void main(String[] args) throws UnsupportedEncodingException {

        //0. 编码
        String s = "字符编码";
        byte[] bytes = s.getBytes("gbk");
        //1. 解码
        String s1 = new String(bytes,"gbk");
        System.out.println(s1);
    }
}
  • 输出
    在这里插入图片描述

2. 字符集

  • 字符编码Character Encoding就是一套字符与二进制数之间的对应规则
  • 字符集Charset:也叫编码表,是一个系统支持所有字符的集合
  • 一套字符集下面至少存在一种编码方式,常见的字符集如下:

在这里插入图片描述

  • 可见字符编码和字符集是一一对应的,指定了编码,则对应的字符集也就随之确定了

下面简单的介绍一下常见的字符集

  • ASCII字符集

    • ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。
    • 基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。
  • ISO-8859-1字符集

    • 拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。
    • ISO-8859-1使用单字节编码,兼容ASCII编码。
  • GBxxx字符集

    • GB就是国标的意思,是为了显示中文而设计的一套字符集。
    • GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。
    • GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等。
    • GB18030:最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。
  • Unicode字符集

    • Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国码。
    • 它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案,UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。
    • UTF-8编码,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。所以,我们开发Web应用,也要使用UTF-8编码。它使用一至四个字节为每个字符编码,编码规则:
      • 8个US-ASCII字符,只需一个字节编码。
      • 拉丁文等字符,需要二个字节编码。
      • 大部分常用字(含中文),使用三个字节编码。
      • 其他极少使用的Unicode辅助字符,使用四字节编码。

3. 编码问题导致的乱码

  • 在Java开发工具IDEA中,使用FileReader读取项目中的文本文件,由于IDEA默认设置UTF-8便阿门,所有没有问题。但是读取Windows创建的文本文件的时候,Windows默认的是GBK编码,就会出现乱码

下面将演示这个问题

  • 在windows下新建一个文本文件
    在这里插入图片描述

  • 使用FileReader读取

public class Charset_Demo02 {
    public static void main(String[] args) throws IOException {

        //0. 新建FileReader对象
        FileReader fr = new FileReader("D:\\IO流学习\\gbk.txt");
        int len;
        while ((len = fr.read()) != -1){
            System.out.print((char)len);
        }
    }
}
  • 输出

在这里插入图片描述

  • 那么如何解决这个问题呢?也就是如何读取GBK编码方式的文件呢!
  • 这个时候就需要转换流了

4. InputStreamReader类–(字节流到字符流的桥梁)

  • java.io.InputStreamReader,是Reader的子类
  • 字面意思就能看出从字节输入流最后到了字符输入流
  • 它本质上是读取字节,然后使用指定的字符集将字节解码为字符
    • 字符集可以自己指定
    • 也可以使用默认的字符集

4.1 构造方法

  • public InputStreamReader(InputStream in):创建一个使用默认字符集的字符流,注意参数是一个InpunStream的对象
  • public InputStreamReader(InputStream in, String charsetName):创建一个使用指定字符集的字符流

具体使用

  InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\IO流学习\\gbk.txt"));
        
InputStreamReader isr1 = new InputStreamReader(new FileInputStream("D:\\IO流学习\\gbk.txt"),"GBK");
        

4.2 解决编码问题

以上面在Windows下创建的GBK编码的文件的读取为例子

public class Charset_Demo02 {
    public static void main(String[] args) throws IOException {

        //0. 使用默认的utf-9
        InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\IO流学习\\gbk.txt"));
        //1. 使用指定的gbk编码
        InputStreamReader isr1 = new InputStreamReader(new FileInputStream("D:\\IO流学习\\gbk.txt"),"GBK");

        System.out.println("使用默认utf-8的读取效果");
        int len;
        while ((len = isr.read()) != -1){
            System.out.print((char)len);
        }
        System.out.println();
        System.out.println("使用指定的gbk的读取效果");
        while ((len = isr1.read()) != -1){
            System.out.print((char)len);
        }

    }
}
  • 输出

在这里插入图片描述

5. OutputStreamWriter–字符流到字节流的桥梁

起始这个也很好理解,首先这显然是一个输出流,既然是输出流,那么就一定是把内存中的数据写入到磁盘上,然后以字节(二进制)的形式存储。这个过程显然就是程序中的字符到磁盘上的字节的转换过程。

5.1 构造方法

  • OutputStreamWriter(OutputStream os):使用默认字符集的字符流
  • OutputStreamWriter(OutputStream os, String charsetName):创建一个指定字符集的字符流

5.2 指定编码输出数据

public class Charset_Demo03 {
    public static void main(String[] args) throws IOException {
        //0. 创建默认字符集编码的 字符输出流
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\IO流学习\\utf.txt"));

        //1. 创建指定字符集编码的 字符输出流
        OutputStreamWriter osw1 = new OutputStreamWriter(new FileOutputStream("D:\\IO流学习\\gbk.txt"),"gbk");

        //2. 分别写入数据s
        osw.write("按默认编码输出的数据");
        osw1.write("按指定gbk编码输出的数据");
        //3. 关闭流
        osw.close();
        osw1.close();
    }
}
  • 输出
    在这里插入图片描述

6. 小结

目前学过的流的一个小节
在这里插入图片描述

二、序列化流

序列化相关问题请参考文章https://blog.csdn.net/fat_cai_niao/article/details/105051846

知道相关的序列化类及其构造函数:

  • ObjectOutputStream
    • public ObjectOutputStream(OutputStream out)
    • public final void writeObject(Object obj)
  • ObjectInputStream
    • public ObjectInputStream(InputStream in)
    • public final Object readObject()

三、打印流

1. 什么是打印流?

  • 在控制台打印信息的时候调用print()println()方法完成的
  • 这个两个方法本质上都来自java.io.PrintStream
  • 该类可以方便的打印各种类型的值,是一种便捷的输出设备

1.1 打印流分类

  • 字节打印流:PrintStream
  • 字符打印流:PrintWriter

1.2 打印流特点

  • 只操作目的地,不操作数据源
  • 可以操作任意类型的数据
  • 如果启用了自动刷新,调用println()方法时,能够换行并刷新
  • 可以直接操作文件

那些流可以直接操作文件呢?

  • 该流的构造方法能够同时接收FileString类型参数的时候,一般都是可以直接操作文件的

2. 字节输出打印流PrintStream复制文本文件

public class Print_Demo01 {
    public static void main(String[] args) throws IOException {
        //0. 新建 缓冲字符输入流
        BufferedReader br = new BufferedReader(new FileReader("D:\\IO流学习\\a.txt"));
        //1. 新建 打印输出流
        PrintStream ps = new PrintStream("D:\\IO流学习\\a_printCopy.txt");
        //2. 按行复制文件
        String line;
        while ((line = br.readLine()) != null){
            ps.println(line);
        }
        br.close();
        ps.close();

    }
}
  • 输出
    在这里插入图片描述

3. 字符打印输出流PrintWriter复制文本文件

public class Print_Demo03 {
    public static void main(String[] args) throws IOException {
        //0. 新建 缓冲字符输入流
        BufferedReader br = new BufferedReader(new FileReader("D:\\IO流学习\\a.txt"));
        //1. 新建 打印输出流
        PrintWriter pw = new PrintWriter("D:\\IO流学习\\a_printCopy_01.txt");
        //2. 按行复制文件
        String line;
        while ((line = br.readLine()) != null){
            pw.println(line);
        }
        br.close();
        pw.close();

    }
}
  • 输出
    在这里插入图片描述

四、Properties属性类

1. 概述

  • 是一个集合类

  • java.util.Properties继承于Hashtable

    • class Properties extends Hashtable<Object,Object>
  • 表示一个持久的属性集,使用键值结构存储数据,每个键值都是一个字符串

  • 该类被多种Java类使用,比如获取系统属性System.getProperties()返回的就是一个Properties对象

1.1 特有功能

  • Object setProperty(String key, String value)
  • public String getProperty(String key)
  • public Set<String> stringPropertyNames()

1.2 与流结合的功能

输出:把内存中的集合类存储到文本文件中

  • public void store(Writer writer, String comments)
  • public void store(OutputStream out, String comments)

输入:把键值对形式的文本文件内容加载到内存中的集合

  • void load(InputStream inStream)
  • void load(Reader reader)

2. 构造方法

public Properties() {
        this(null);
    }

3. 基本存储方法

  • Object setProperty(String key, String value):保存一对键值对
  • public String getProperty(String key):根据键,获取值
  • public Set<String> stringPropertyNames():获取所有的键

使用

public class Properties_Demo01 {
    public static void main(String[] args) {
        //0. 创建属性对象
        Properties properties = new Properties();
        //1. 添加键值对
        properties.setProperty("fileName", "pro.txt");
        properties.setProperty("length", "20985038");
        properties.setProperty("location", "D:\\IO流学习\\pro.txt");
        //2. 打印属性集对象
        System.out.println(properties);
        //3. 通过键获取值
        System.out.println(properties.getProperty("fileName"));
        System.out.println(properties.getProperty("length"));
        System.out.println(properties.getProperty("location"));
        //4. 获取所有的键名 并遍历
        Set<String> names = properties.stringPropertyNames();
        for (String name : names) {
            System.out.println(name + "---->" + properties.getProperty(name));
        }
    }
}
  • 输出
    在这里插入图片描述

4. 与流相关

  • void load(InputStream inStream) :从字节输入流中获取键值对

因为参数中使用了字节输入流,可以关联到某文件,这样就可以加载文本中的数据了。就是可以把文件中的键值对加载到内存中,常用于配置文件。

public class Properties_Demo02 {
    public static void main(String[] args) throws IOException {
        //0. 创建属性对象
        Properties properties = new Properties();
        //1. 加载文本信息到属性集
        properties.load(new FileInputStream("D:\\IO流学习\\pro.txt"));
        //2. 遍历并打印
        Set<String> set = properties.stringPropertyNames();
        for (String key : set) {
            System.out.println(key + "--->" + properties.getProperty(key));
        }
    }
}

  • 输出
    在这里插入图片描述
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值