IO

IO 概述

1. IO的分类

根据数据的流向:输入流和输出流

根据数据的类型:字节流和字符流

2. 顶级父类

输出流输入流
字节流OutputStreamInputStream
字符流WriterReader

字节流

1. 字节输出流 -> OutputStream

主要方法:

  • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
  • public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
  • public void write(byte[] b):将 b.length字节从指定的字节数组写入此输出流。
  • public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。
  • public abstract void write(int b) :将指定的字节输出流。

2.通过字节流写一个文件

public static void writeFIleByOutPutStream() throws IOException {
    // 创建一个输出流对象
    FileOutputStream fos = new FileOutputStream("1.txt");
    // 向文件中写入字节数据
    fos.write("这是一个字节输出流写的文件".getBytes());
    fos.close();
}

3. 字节输入流 -> InputStream

  • public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
  • public abstract int read(): 从输入流读取数据的下一个字节。
  • public int read(byte[] b): 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。

4. 通过字节输入流读取文件

public static void readFileByInputStream() throws IOException {
    // 创建一个字节输入流
    FileInputStream fis = new FileInputStream("1.txt");
    // 定义一个字节数组
    byte[] bytes = new byte[1024];
    // 定义一个有效长度变量
    int len;
    // 开始读取文件
    while ((len = fis.read(bytes)) != -1) {
        // 输出
        System.out.println(new String(bytes, 0, len));
    }
    // 关闭资源
    fis.close();
}

5. 通过字节流复制一个文件

public static void main(String[] args) throws IOException {
    // 创建一个文件字节输入流
    FileInputStream fis = new FileInputStream("C:\\Users\\WH\\Desktop\\高等数学(II-2).docx");
    // 创建一个文件字节输出流
    FileOutputStream fos = new FileOutputStream("这是字节流程复制的文件-1.docx");
    // 定义有效个数变量
    int len;
    // 定义一个1024 长度的字节数组
    byte[] chars = new byte[1024];
    // 开始读取文件,并写入 输出流
    while ((len = fis.read(chars)) != -1) {
        fos.write(chars,0, len);
        System.out.println(new String(chars, 0, len));
    }
    fos.close();
    fis.close();
}

字符流

1. 字符输出流程 -> Writer

  • void write(int c) 写入单个字符。
  • void write(char[] cbuf)写入字符数组。
  • abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
  • void write(String str)写入字符串。
  • void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
  • void flush()刷新该流的缓冲。
  • void close() 关闭此流,但要先刷新它。

2. 通过字符输出流创建写一个文件

public static void writeFileByFileWriter() throws IOException {
    // 创建一个 字符输出流程对象
    FileWriter fw = new FileWriter("2.txt");
    // 写出数据
    fw.write(97); // 写出第1个字符

    fw.write('b'); // 写出第2个字符
    fw.write('C'); // 写出第3个字符
    fw.write(30000); // 写出第4个字符,中文编码表中30000对应一个汉字。
    fw.write("\r\n".toCharArray());
    // 刷新缓冲区
    fw.flush();

    // 写入字符数组
    char[] chars = "这是一个字符数组".toCharArray();
    fw.write(chars);
    fw.write("\r\n".toCharArray());
    // 刷新缓冲区
    fw.flush();
    // 写入字符串
    fw.write("这是一个字符串");
    fw.write("\r\n");

    fw.close();
}

小贴士:

  1. 虽然参数为int类型四个字节,但是只会保留一个字符的信息写出。
  2. 未调用close方法,数据只是保存到了缓冲区,并未写出到文件中。
  3. 即便是flush方法写出了数据,操作的最后还是要调用close方法,释放系统资源。

关闭和刷新

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush 方法了。

  • flush :刷新缓冲区,流对象可以继续使用。
  • close:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

3. 字符输入流 -> Reader

  • public void close() :关闭此流并释放与此流相关联的任何系统资源。
  • public int read(): 从输入流读取一个字符。
  • public int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。

4. 通过字符输入流程读取一个文件

public static void readFileByFileReader() throws IOException {
    // 创建一个 字符输入流
    FileReader fr = new FileReader("2.txt");
    // 创建一个字符数组
    char[] chars = new char[1024];
    int len;
    System.out.println("通过字符数组读取==========================================");
    while ((len = fr.read(chars)) != -1) {
        System.out.println(new String(chars));
    }
    System.out.println("通过字符读取==========================================");
    // 创建一个 字符输入流
    FileReader fr2 = new FileReader("2.txt");
    int b;
    while ((b = fr2.read()) != -1) {
        System.out.println((char) b);
    }
    fr.close();
}

写出换行

  • 回车符\r和换行符\n
    • 回车符:回到一行的开头(return)。
    • 换行符:下一行(newline)。
  • 系统中的换行:
    • Windows系统里,每行结尾是 回车+换行 ,即\r\n
    • Unix系统里,每行结尾只有 换行 ,即\n
    • Mac系统里,每行结尾是 回车 ,即\r。从 Mac OS X开始与Linux统一。

缓冲流

1. 概述

缓冲流,也叫高效流,是对4个基本的FileXxx 流的增强,所以也是4个流,按照数据类型分类:

  • 字节缓冲流:BufferedInputStreamBufferedOutputStream

  • 字符缓冲流:BufferedReaderBufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

2. 字节缓冲流

2.1 构造方法

  • public BufferedInputStream(InputStream in) :创建一个 新的缓冲输入流。
  • public BufferedOutputStream(OutputStream out): 创建一个新的缓冲输出流。

2.2 使用缓冲流改造字节流

public static void copyFileByBufferedStream() throws IOException {
    // 创建一个缓冲字节输入流
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream("C:\\Users\\WH\\Pictures\\屏幕截图 2020-12-29 230816.png"));
    // 创建一个缓冲字节输出流
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("图片-copy-buffered.png"));
    // 定义有效个数变量
    int len;
    // 定义一个1024 长度的字节数组
    byte[] byte= new byte[1024];
    // 开始读取文件,并写入 输出流
    while ((len = bis.read(byte)) != -1) {
    bos.write(chars,0, len);
    }
    bos.close();
    bis.close();
}

3. 字符缓冲流

3.1 构造方法

  • public BufferedReader(Reader in) : 创建以新的缓冲输入流
  • public BufferedWrite(Writer out): 创建一个新的缓冲输出流

3.2 特有方法

字符缓冲流的基本方法与普通字符流调用方式一致,不再阐述,我们来看它们具备的特有方法。

  • BufferedReader:public String readLine(): 读一行文字。
  • BufferedWriter:public void newLine(): 写一行行分隔符,由系统属性定义符号。

3.3 通过readLine() 读取文件

public static void readFileByBufferedReader() throws IOException {
    // 创建一个 字符输入缓冲流
    BufferedReader br = new BufferedReader(new FileReader("2.txt"));
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
        System.out.println("===============================");
    }
    br.close();
}

3.4 通过字符缓冲流复制一个文件

public static void copyFileByBufferedStream() throws IOException {
    // 创建一个 字符输入缓冲流
    BufferedReader br = new BufferedReader(new FileReader("2.txt"));
    // 创建一个 字符输出缓冲流
    BufferedWriter bw = new BufferedWriter(new FileWriter("copy-2.txt"));
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
        System.out.println("===============================");
        bw.write(line);
        bw.newLine();
    }
    bw.close();
    br.close();
}

转换流

1. 概述

字符编码

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

编码:字符(能看懂的)–字节(看不懂的)

解码:字节(看不懂的)–>字符(能看懂的)

2. InputStreamReader-> 字节流通向字符流的桥梁

2.1 构造函数

  • InputStreamReader(InputStream in):创建一个使用系统默认字符集的字符流
  • InputStreamReader(InputStream in, String charsetName):创建指定字符集字符流

2.2 指定字符集读取文件

public static void readFile() throws IOException {
    // 创建一个 字节转换字符流
    InputStreamReader isr = new InputStreamReader(new FileInputStream("C:\\Users\\WH\\Desktop\\gb2312.txt"));
    // 默认字符集读
    int len;
    char[] chars = new char[1024];
    System.out.println("默认字符集读文件============================");
    while ((len = isr.read(chars)) != -1) {
        System.out.println(new String(chars));
    }

    // 创建一个 字节转换字符流
    InputStreamReader isr2 = new InputStreamReader(new FileInputStream("C:\\Users\\WH\\Desktop\\gb2312.txt"),"gb2312");
    System.out.println("指定gb2312字符集读文件============================");
    char[] read = new char[1024];
    while ((len = isr2.read(read)) != -1) {
        System.out.println(new String(read));
    }
    isr.close();
    isr2.close();
}

3. OutputStreamWriter -> 字符流到字节流的桥梁

3.1 构造方法

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

3.2 指定编码写文件


public static void writeFile() throws IOException {
    // 创建一个指定字符的流对象
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"),"gbk");
    // 向文件中写数据
    osw.write("你好");
    osw.flush();
    osw.close();

    // 创建一个不指定字符的流对象
    OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream("no-gbk.txt"));
    // 向文件中写数据
    osw2.write("你好");
    osw2.flush();
    osw2.close();
}

4. 图解

InputStreamReader读取字节,解码为字符

字节 -------------------------------------> 字符

OutputStreamWriter写出字符,编码为字节

  • 11
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值