当前位置:网站首页>2022-08-09 学习笔记 day32-IO流

2022-08-09 学习笔记 day32-IO流

2022-08-10 18:05:00 激进的韭菜

IO流

什么是IO?
  I:input (输入)
  O: output (输出)
  IO:通过io完成对文件的读和写

什么是IO流?
  是内存和硬盘空间某个文件之间的通道,可以完成对文件的读和写

流的分类

  1. 按照流向 (以内存为参照物)
    从硬盘空间 ———> 内存 (输入/读)
    从内存 ———> 硬盘空间 (输出/写)

  2. 按照操作单元(读取数据方式)
    字节流 ——> 按字节读取 (可以操作所有的文件)
    字符流——> 按字符读取 (只能操作文本文件[.txt/.html/.java等])

  3. 按角色划分
    节点流:直接操作的是一个特定的IO流
    处理流:在节点流的基础上,做进一步的处理

    当一个流的构造方法中需要一个流的时候,这个被传进去的流叫做节点流
    外部负责包装的流叫做包装流/处理流,节点流和包装流是相对的

Colseable接口

所有的流都实现类Colseable接口,表示他们都是可关闭的close()

close() ----> 关闭流

  1. 所有的流(除了标准输出流)都需要手动关闭 (Java7之前)
  2. 要确保流一定能关闭,不关闭流会占用大量资源,可以将close()放到finally语句块中
  3. 对流关闭时,要先做非空判断,避免NPE
  4. 流的关闭顺序:先开后关,后开先关
  5. 包装流和节点流的关闭:只需要关闭包装流即可
  6. 对于输出流来说,使用close()后就不需要在flush()

AutoCloseable接口(Java7)

由于Closeable继承了AutoCloseable接口,表示所有的流,都是可自动关闭的
使用新语法:try-with-resource
-----> 在try的”()“中声明并初始化实现AutoClosealbe接口的流。

public class Demo {
    
	@Test
    public void testAutoColse() {
       
        byte[] datas = {
    73, 32, 76, 111, 118, 101, 32, 89, 111, 117};
        // 新语法 try-with-resource
        try (OutputStream out = new FileOutputStream("1.txt")) {
    
            out.write(datas);
        } catch (FileNotFoundException e) {
    
            e.printStackTrace();
        } catch (IOException e) {
    
            e.printStackTrace();
        }
    }
}

Java9之后,对try-with-resource语法进行了简化,”()“里面可以是一个变量,但必须是final的或者等同final才行。

public class Demo {
    
	 @Test
    public void testAutoColse() throws FileNotFoundException {
    
        byte[] datas = {
    73, 32, 76, 111, 118, 101, 32, 89, 111, 117};
        OutputStream out = new FileOutputStream("1.txt");
        try (out) {
    
            out.write(datas);
        } catch (FileNotFoundException e) {
    
            e.printStackTrace();
        } catch (IOException e) {
    
            e.printStackTrace();
        }
    }
}

Flushable接口

所有的输出流(InputStream/Writer)都实现了Flushable接口,表示所有的输出流都是可刷新的flush()

flush() ----> 刷新流
注意close()具有flush()的功能
flush()表示将通道剩余未输出的数据强行输出(清空管道),如果没有flush()可能会丢失数据
具体可以看下面的例子

public class Demo {
    
	 @Test
    public void testFlush() throws IOException{
    
        char[] datas = {
    73, 32, 76, 111, 118, 101, 32, 89, 111, 117};
        BufferedWriter writer = new BufferedWriter(new FileWriter("1.txt"));
        writer.write(datas);
        
        // writer.flush();
    }
}

在这里插入图片描述

流的四大家族首领

字节流
	java.io.InputStream ----> 字节输入流
	java.io.OutputStream ----> 字节输出流
字符流
	java.io.Reader ----> 字符输入流
	java.io.Writer ----> 字符输出流

需要掌握的16个流

文件专属

FileInputStream类

  1. 包路径:java.io.FileInputStream

  2. 继承关系:
    在这里插入图片描述

  3. 构造方法在这里插入图片描述

  4. 方法
    在这里插入图片描述

FileOutputStream类

  1. 包路径:java.io.FileOutputStream

  2. 继承关系
    在这里插入图片描述

  3. 构造方法(输出流初始化时——重点)
    在这里插入图片描述

FileReader类

  1. 包路径:java.io.FileReader
  2. 继承关系
    在这里插入图片描述
  3. 对于构造方法和方法,没什么需要特别注意的地方,具体内容请查看帮助文档

FileWriter类

  1. 包路径:java.io.FileWriter

  2. 继承关系
    在这里插入图片描述

  3. 对于构造方法和方法,没什么需要特别注意的地方,具体内容请查看帮助文档

缓冲流

带缓冲区的输出流要记得flush()或close(),否则会导致数据丢失

BufferedInputSteam类

  1. 包路径:java.io.BufferedInputStream
  2. 继承关系
    在这里插入图片描述
  3. 方法

BufferedOutputStream类

  1. 包路径:java.io.BufferedOutputStream
  2. 继承关系
    在这里插入图片描述

BufferedReader类

  1. 包路径:java.io.BufferedReader

  2. 继承关系
    在这里插入图片描述

  3. 构造方法
    在这里插入图片描述

  4. 方法
    在这里插入图片描述

BufferedWriter类

  1. 继承关系
  2. 构造方法
    在这里插入图片描述
  3. 方法
    在这里插入图片描述

转换流

  将字节流转换成字符流:字节流 ----> 转换流(字符流) 可以指定字符集

InputStreamReader类

  1. 包路径:java.io.InputStreamReader

  2. 继承关系
    在这里插入图片描述

  3. 构造方法
    在这里插入图片描述

指定字符集
public class Demo01 {
    
	@Test
    public void testInputStreamReader() throws IOException {
    
        // 未指定字符集,使用默认字符集(此处是UTF-8),在使用reader()方法读取文件数据时,以UTF-8字符集对文件数据进行(解码)
        InputStreamReader reader1 = new InputStreamReader(new FileInputStream("temp.txt"));
        // 指定字GBK符集,在使用reader()方法读取文件数据时,以GBK字符集对文件数据进行(解码)
        InputStreamReader reader2 = new InputStreamReader(new FileInputStream("temp.txt"),"GBK");

    }
}
读取文件时的乱码问题与解决方案

案例:当默认字符集为UTF-8时,尝试对这个GBK编码的文件进行读取
在这里插入图片描述
具体代码如下

public class Demo01 {
    
	 @Test
    public void testInputStreamReader() {
    
        // 未指定字符集,使用默认字符集(此处是UTF-8),在使用reader()方法读取文件数据时,以UTF-8字符集对文件数据进行(解码)
        try(InputStreamReader reader1 = new InputStreamReader(new FileInputStream("temp.txt"));) {
    
            int data;
            while ((data = reader1.read()) != -1) {
    
                System.out.println(data + " ----> " + (char) data);
            }
        } catch (FileNotFoundException e) {
    
            e.printStackTrace();
        } catch (IOException e) {
    
            e.printStackTrace();
        }
    }
}

结果如下
在这里插入图片描述
为什么会出现乱码呢?

由于在reader初始化时并未指定字符集,所以采用默认字符集(此处默认时UTF-8),所以使用reader对字节流进行读取时,会使用用UTF-8字符集进行解码1,而文件采用的编码方式时GBK,编码与解码所指定的字符集不同,所以此处出现乱码。

  1. 设置默认字符集为GBK(不推荐)
    在这里插入图片描述
    将Global Encoding设置为GBK
  2. 在InputStreamReader初始化时指定字符集为GBK

在这里插入图片描述

采用这两种方式,文件可以正常读取了
在这里插入图片描述

OutputStreamWriter类

  1. 包路径:java.io.OutputStreamWriter
  2. 继承关系
    在这里插入图片描述
  3. 构造方法
    在这里插入图片描述
指定字符集
public class Demo01 {
    
	 @Test
    public void testOutputStreamWriter() throws FileNotFoundException {
    
        // 未指定字符集,使用默认字符集(此处是UTF-8),在使用writer()方法将数据写入文件时,以UTF-8字符集对数据进行(编码)
        OutputStreamWriter writer1 = new OutputStreamWriter(new FileOutputStream("temp.txt"));
        // 未指定字符集,使用默认字符集(此处是UTF-8),在使用writer()方法将数据写入文件时,以UTF-8字符集对数据进行(编码)
        OutputStreamWriter writer2 = new OutputStreamWriter(new FileOutputStream("temp.txt"));
    }
}

注意:
如果文件不存在,则创建指定字符集的文件
如果文件存在,未设置追加,则创建指定字符集文件并覆盖原文件
如果文件存在,并设置了追加,则不会覆盖原文件也不会改变原文件编码所用字符集

写入文件时出现的乱码问题与解决方案

数据流

标准输出流

  注意:标准输出流不需要手动close(),但一定要flush(),尤其是带缓冲区的流

PrintStream类

  1. 包路径:java.io.PrintStream
  2. 继承关系
    在这里插入图片描述
  3. 对于构造方法和方法,没什么需要特别注意的地方,具体内容请查看帮助文档

我们常用的输出语句"System.out.println()",便用到了标准输出流,其中"out"便是System类下的一个静态属性,这个“out”是PrintStream类型,默认将内容输出到控制台。那么我们可以更改输出语句的输出位置么?答案是可以的,我们可以通过调用"System.setOut()"这个方法来设置out属性。

获取System.out
package com.jsoft.io;

import org.junit.Test;
import java.io.*;

public class Demo01 {
    
	 public void testPrintStream() {
    
        // 获取System.out
        PrintStream myOut = System.out;
        // 向控制台输出内容
        myOut.println("潘翀,我是你爹");
    }
}
更改System.out (更改输出语句的输出位置)
package com.jsoft.io;

import org.junit.Test;
import java.io.*;

public class Demo01 {
    
	@Test
   public void testPrintStream() throws FileNotFoundException {
    

       PrintStream myOut = new PrintStream("temp.txt");
       // 更改System.out的输出位置(控制台 ---> temp.txt)
       System.setOut(myOut);
       System.out.println("向temp.txt输出的内容");

       // 将System.out修改回原输出位置(temp.txt ---> 控制台)
       System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
       System.out.println("向控制台输出的内容");
   }
}

在这里插入图片描述

PrintWriter类

  1. 包路径:java.io.PrintWriter

  2. 继承结构
    在这里插入图片描述

  3. 对于构造方法和方法,和PrintStream基本没啥区别,具体内容请查看帮助文档

对象专属流


  1. 解码:将字节按指定的字符集转换成字符
    那么我们该怎么才能读取GBK呢?

原网站

版权声明
本文为[激进的韭菜]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_56090951/article/details/126240560