十一、缓冲流

需要学会什么?

  • 缓冲流:之前学习的流都属于基础流,性能不是最好的,缓冲流读写数据的性能更好。
  • 转换流:使用字符流读取中文不会乱码原始是什么?如果读取的文件编码与代码编码不一致怎么办?
  • 序列化:如何把Java对象进行长久保存。
  • 打印流:开发中有一种使用极为方便、性能高效的写数据的流,使用很多。
  • IO框架等:IO流原生的API使用起来其实挺麻烦的,有没有更好用的方式。

1.缓冲流

a.缓冲流概述

缓冲流概述:

  • 缓冲流也称为高效流、或者高级流。之前学习的字节流可以称为原始流。
  • 作用:缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能。
#mermaid-svg-rFxXFVuMNTmglewh {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-rFxXFVuMNTmglewh .error-icon{fill:#552222;}#mermaid-svg-rFxXFVuMNTmglewh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rFxXFVuMNTmglewh .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-rFxXFVuMNTmglewh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rFxXFVuMNTmglewh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rFxXFVuMNTmglewh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rFxXFVuMNTmglewh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rFxXFVuMNTmglewh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rFxXFVuMNTmglewh .marker.cross{stroke:#333333;}#mermaid-svg-rFxXFVuMNTmglewh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rFxXFVuMNTmglewh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rFxXFVuMNTmglewh .cluster-label text{fill:#333;}#mermaid-svg-rFxXFVuMNTmglewh .cluster-label span{color:#333;}#mermaid-svg-rFxXFVuMNTmglewh .label text,#mermaid-svg-rFxXFVuMNTmglewh span{fill:#333;color:#333;}#mermaid-svg-rFxXFVuMNTmglewh .node rect,#mermaid-svg-rFxXFVuMNTmglewh .node circle,#mermaid-svg-rFxXFVuMNTmglewh .node ellipse,#mermaid-svg-rFxXFVuMNTmglewh .node polygon,#mermaid-svg-rFxXFVuMNTmglewh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rFxXFVuMNTmglewh .node .label{text-align:center;}#mermaid-svg-rFxXFVuMNTmglewh .node.clickable{cursor:pointer;}#mermaid-svg-rFxXFVuMNTmglewh .arrowheadPath{fill:#333333;}#mermaid-svg-rFxXFVuMNTmglewh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rFxXFVuMNTmglewh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rFxXFVuMNTmglewh .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-rFxXFVuMNTmglewh .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-rFxXFVuMNTmglewh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rFxXFVuMNTmglewh .cluster text{fill:#333;}#mermaid-svg-rFxXFVuMNTmglewh .cluster span{color:#333;}#mermaid-svg-rFxXFVuMNTmglewh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rFxXFVuMNTmglewh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

字节缓冲输入流
字节缓冲输出流
字符缓冲输入流
字符缓冲输出流
IO流体系
字节流
字符流
InputStream-抽象类
FileInputStream-实现类
BufferedInputStream-实现类
OutputStream-抽象类
FileOutputStream-实现类
BufferedOutputStream-实现类
Reader-抽象类
FileReader-实现类
BufferedReader-实现类
Writer-抽象类
FileWriter-实现类
BufferedWriter-实现类

总结:

  1. 缓冲流的作用?

    • 缓冲流自带缓冲区、可以提高原始字节流、字符流读写数据的性能。
  2. 缓冲流有几种?
    • 字节缓冲流:

      • 字节缓冲输入流:BufferedInputStream。
      • 字节缓冲输出流:BufferedOutputStream。
    • 字符缓冲流:
      • 字符缓冲输入流:BufferedReader。
      • 字符缓冲输出流:BufferedWriter。

b.字节缓冲流

字节缓冲流性能优化原理:

  • 字节缓冲输入流自带了8KB缓冲池,以后我们直接从缓冲池读取数据,所以性能较好。
  • 字节缓冲输出流自带了8KB缓冲池,数据就直接写入到缓冲池中去,写数据性能极高。

Test.java

import java.io.*;public class Test {public static void main(String[] args) throws Exception {try (// 创建一个字节流输入管道与原文件接通InputStream inputStream = new FileInputStream("day11-oop-demo/src/oldData.txt");// 把原始的字节输入流管道包装成高级的缓冲字节输入流InputStream inputStreamBuffered = new BufferedInputStream(inputStream);// 创建一个字节输出流管道于目标文件接通OutputStream outputStream = new FileOutputStream("day11-oop-demo/src/newData.txt");// 把字节输出流管道包装成高级的缓冲字节输出流管道OutputStream outputStreamBuffered = new BufferedOutputStream(outputStream);) {// 定义一个字节数组转移数据byte[] bytes = new byte[1024];// 记录每次读取的字节数int length;while ((length = inputStreamBuffered.read(bytes)) != -1) {outputStreamBuffered.write(bytes, 0, length);}System.out.println("拷贝完成!");} catch (Exception e) {e.printStackTrace();}}
}

总结:

  1. 字节缓冲流为什么提高了操作数据的性能?

    • 字节缓冲流自带8KB缓冲区。
    • 可以提高原始字节流、字符流读写数据的性能。
  2. 字节缓冲流的功能如何调用?
    • public BufferedOutputStrem(OutputStream os)
    • public BufferedInputStrem(InputStream is)

c.字节缓冲流的性能分析

  1. 已经说明了字节缓冲流的性能高效,但是没有直观感受。
  2. 如何测试字节缓冲流的读写性能?

分别使用不同的方式复制大视频观察性能情况。

需求:

  • 分别使用低级字节流和高级字节缓冲流拷贝大视频,记录耗时。

分析:

  1. 使用低级的字节流按照一个一个字节的形式复制文件。
  2. 使用低级的字节流按照一个一个字节数组的形式复制文件。
  3. 使用高级的缓冲字节流按照一个一个字节的形式复制文件。
  4. 使用高级的缓冲字节流按照一个一个字节数组的形式复制文件。

Test.java

import java.io.*;public class Test {private static final String SRC_FILE = "day11-oop-demo/src/可惜没如果.mp4";private static final String DEST_FILE = "day11-oop-demo/src/";public static void main(String[] args) {// 使用低级的字节流按照一个一个字节的形式复制文件copy1();// 使用低级的字节流按照一个一个字节数组的形式复制文件copy2();// 使用高级的缓冲字节流按照一个一个字节的形式复制文件copy3();// 使用高级的缓冲字节流按照一个一个字节数组的形式复制文件copy4();}/*** 使用高级的缓冲字节流按照一个一个字节数组的形式复制文件*/private static void copy4() {long startTime = System.currentTimeMillis();try (// 创建一个字节流输入管道与原文件接通InputStream inputStream = new FileInputStream(SRC_FILE);// 把原始的字节输入流管道包装成高级的缓冲字节输入流InputStream inputStreamBuffered = new BufferedInputStream(inputStream);// 创建一个字节输出流管道于目标文件接通OutputStream outputStream = new FileOutputStream(DEST_FILE + "video4.mp4");// 把字节输出流管道包装成高级的缓冲字节输出流管道OutputStream outputStreamBuffered = new BufferedOutputStream(outputStream);) {// 定义一个字节数组转移数据byte[] bytes = new byte[1024];// 记录每次读取的字节数int length;while ((length = inputStreamBuffered.read(bytes)) != -1) {outputStreamBuffered.write(bytes, 0, length);}System.out.println("拷贝完成!");} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("使用高级的缓冲字节流按照一个一个字节数组的形式复制文件:" + (endTime - startTime) / 1000.0 + "秒");}/*** 使用高级的缓冲字节流按照一个一个字节的形式复制文件*/private static void copy3() {long startTime = System.currentTimeMillis();try (// 创建一个字节流输入管道与原文件接通InputStream inputStream = new FileInputStream(SRC_FILE);// 把原始的字节输入流管道包装成高级的缓冲字节输入流InputStream inputStreamBuffered = new BufferedInputStream(inputStream);// 创建一个字节输出流管道于目标文件接通OutputStream outputStream = new FileOutputStream(DEST_FILE + "video3.mp4");// 把字节输出流管道包装成高级的缓冲字节输出流管道OutputStream outputStreamBuffered = new BufferedOutputStream(outputStream);) {// 定义一个变量记录每次读取的字节int b;while ((b = inputStreamBuffered.read()) != -1) {outputStreamBuffered.write(b);}System.out.println("拷贝完成!");} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("使用高级的缓冲字节流按照一个一个字节的形式复制文件:" + (endTime - startTime) / 1000.0 + "秒");}/*** 使用低级的字节流按照一个一个字节数组的形式复制文件*/private static void copy2() {long startTime = System.currentTimeMillis();try (// 创建低级的字节输入流于源文件接通InputStream inputStream = new FileInputStream(SRC_FILE);// 创建低级的字节输出流与目标文件接通OutputStream outputStream = new FileOutputStream(DEST_FILE + "video2.mp4")) {// 定义一个变量记录每次读取的字节byte[] bytes = new byte[1024];// 记录每次读取的字节数int length;while ((length = inputStream.read(bytes)) != -1) {outputStream.write(bytes, 0, length);}System.out.println("拷贝完成!");} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("使用低级的字节流按照一个一个字节数组的形式复制文件:" + (endTime - startTime) / 1000.0 + "秒");}/*** 使用低级的字节流按照一个一个字节的形式复制文件*/private static void copy1() {long startTime = System.currentTimeMillis();try (// 创建低级的字节输入流于源文件接通InputStream inputStream = new FileInputStream(SRC_FILE);// 创建低级的字节输出流与目标文件接通OutputStream outputStream = new FileOutputStream(DEST_FILE + "video1.mp4")) {// 定义一个变量记录每次读取的字节int b;while ((b = inputStream.read()) != -1) {outputStream.write(b);}System.out.println("拷贝完成!");} catch (Exception e) {e.printStackTrace();}long endTime = System.currentTimeMillis();System.out.println("使用低级的字节流按照一个一个字节的形式复制文件耗时:" + (endTime - startTime) / 1000.0 + "秒");}
}

程序输出结果:

拷贝完成!
使用低级的字节流按照一个一个字节的形式复制文件耗时:529.098秒
拷贝完成!
使用低级的字节流按照一个一个字节数组的形式复制文件:1.149秒
拷贝完成!
使用高级的缓冲字节流按照一个一个字节的形式复制文件:11.206秒
拷贝完成!
使用高级的缓冲字节流按照一个一个字节数组的形式复制文件:0.598秒

总结:

  1. 推荐使用哪种方式提高字节流读写数据的性能?

    • 建议使用字节缓冲输入流、字节缓冲输出流,结合字节数组的方法,目前来看是性能最优的组合。

d.字符缓冲流

字符缓冲输入流:

  • 字符缓冲输入流:BufferedReader。
  • 作用:提高字符输入流读取数据的性能,除此之外多了按照行读取数据的功能。
构造器 说明
public BufferedReader(Reader r) 可以把低级的字符输入流包装成一个高级的缓冲字符输入流管道,从而提高字符输入流读数据的性能。

Test.java

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;/*** 目标:学会使用缓冲字符输入流提高字符输入流的性能,新增了按照行读取的方法(经典代码)*/
public class Test {public static void main(String[] args) {try (// 创建一个文件字符输入流与源文件接通Reader reader = new FileReader("day11-oop-demo/src/oldData.txt");// 把低级的字符输入流包装成高级的缓冲字符输入流BufferedReader bufferedReader = new BufferedReader(reader);) {//            char[] chars = new char[1024];
//
//            int len;
//
//            while ((len = bufferedReader.read(chars)) != -1) {//                String string = new String(chars, 0, len);
//                System.out.println(string);
//            }// 读一行
//            System.out.println(bufferedReader.readLine());/* 经典代码 */String line;while ((line = bufferedReader.readLine()) != null) {System.out.println(line);}} catch (Exception e) {e.printStackTrace();}}
}

字符缓冲输出流:

  • 字符缓冲输出流:BufferedWriter。
  • 作用:提高字符输出流写数据的性能,除此之外多了换行功能。
构造器 说明
public BufferedWriter(Writer w) 可以把低级的字符输入流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能。
方法 说明
public void newLine() 换行操作。

Test.java

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.Writer;/*** 目标:缓冲字符输出流管道的使用,学会它多出来多一个功能:newLine()*/
public class Test {public static void main(String[] args) throws Exception{// 创建一个字符输出流管道与目标文件接通Writer writer = new FileWriter("day11-oop-demo/src/newData.txt");// 追加//Writer writer = new FileWriter("day11-oop-demo/src/newData.txt", true);BufferedWriter bufferedWriter = new BufferedWriter(writer);bufferedWriter.write("Java");bufferedWriter.write("Python");bufferedWriter.newLine();bufferedWriter.flush();bufferedWriter.close();}
}

总结:

  1. 字符缓冲流为什么提高了操作数据的性能?

    • 字符缓冲流自带8K缓冲区。
    • 可以提高原始字节流读写数据的性能。
  2. 字符缓冲流的功能如何使用?
    • public BufferedReader(Reader r)
    • 性能提升了,多了readLine()按照行读写的功能。
    • public BufferedWriter(Writer w)
    • 性能提升了,多了newLine()换行的功能。

案例:拷贝出师表到另一个文件,恢复顺序。

需求:

  • 把《出师表》的文章顺序进行恢复到一个新文件中。

    一、先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
    九、今当远离,临表涕零,不知所言。
    二、宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
    八、愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
    四、将军向宠,性行淑均,晓畅军事,试用于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
    三、侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必能裨补阙漏,有所广益。
    六、臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
    五、亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。
    七、先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐托付不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
    

分析:

  1. 定义一个缓冲字符输入流管道与源文件接通。
  2. 定义一个List集合存储读取的每行数据。
  3. 定义一个循环按照行读取数据,存入到List集合中去。
  4. 对List集合中的每行数据按照首字符编号升序排序。
  5. 定义一个缓冲字符输出管道与目标文件接通。
  6. 遍历List集合中的每个元素,用缓冲输出管道写出并换行。

Test.java

import java.io.*;
import java.util.*;public class Test {public static void main(String[] args) {try (// 创建缓冲字符输入流管道与源文件接通BufferedReader bufferedReader = new BufferedReader(new FileReader("day11-oop-demo/src/出师表-乱序.txt"));// 定义缓冲字符输出管道与目标文件接通BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("day11-oop-demo/src/出师表-正序.txt"));){/* 读取内容 */// 定义一个List集合存储每行内容List<String> list = new ArrayList<>();// 定义循环 按照行读取文章String line;while ((line = bufferedReader.readLine()) != null) {list.add(line);}/* 排序 */// 自定义排序规则List<String> sizes = new ArrayList<>();// 按照大小加入Collections.addAll(sizes, "一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二");Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String s1, String s2) {// 获取索引比较大小return sizes.indexOf(s1.substring(0, s1.indexOf("、"))) - sizes.indexOf(s2.substring(0, s2.indexOf("、")));}});System.out.println(list);/* 写入 */// 遍历集合中的每行文字写入文件中for (String s : list) {bufferedWriter.write(s);// 换行bufferedWriter.newLine();}} catch (Exception e) {e.printStackTrace();}}
}

2.转换流

  1. 之前我们使用字符流读取中文是否乱码?

    • 没有乱码,因为代码编码和文件编码都是UTF-8。
  2. 如果代码编码和文件编码不一致,使用字符流直接读取还能不乱码吗?
    • 会乱码。
    • 文件编码和读取的编码必须一致才不会乱码。

a.问题引出:不同编码读取乱码问题

使用相同编码读取不同编码的文件内容:

需求:分别使用如下两种方式读取文件内容。

  • 代码编码是UTF-8,文件编码也是UTF-8,使用字符流读取观察输出的中文字符结果。
  • 代码编码是UTF-8,文件编码使用GBK,使用字符流读取观察输出的中文字符结果。

CharSetDemo.java

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;/*** 演示一下代码编码与文件编码相同和不同的情况*/
public class CharSetDemo {public static void main(String[] args) {try (/* 代码: UTF-8 文件: UTF-8 不会乱码 */// 创建一个文件字符输入流与源文件接通Reader reader = new FileReader("day11-oop-demo/src/utf-8Data.txt");/* 代码: UTF-8 文件: GBK 乱码 */Reader reader1 = new FileReader("day11-oop-demo/src/gbkData.txt");// 把低级的字符输入流包装成高级的缓冲字符输入流BufferedReader bufferedReader = new BufferedReader(reader);BufferedReader bufferedReader1 = new BufferedReader(reader1);) {/* 经典代码 */String line;while ((line = bufferedReader.readLine()) != null) {System.out.println(line);}String line1;while ((line1 = bufferedReader1.readLine()) != null) {System.out.println(line1);}} catch (Exception e) {e.printStackTrace();}}
}

b.字符输入转换流

  1. 如果代码编码和文件编码不一致,使用字符流直接读取还能不乱码吗?

    • 会乱码。
  2. 如何解决?

    • 使用字符输入转换流

    • 可以提取文件(GBK)的原始字节流,原始字节不会存在问题。

    • 然后把字节流以指定编码转换成字符输入流,这样字节输入流中的字符就不乱码了。

#mermaid-svg-XgEtuocdFaKuxA1G {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-XgEtuocdFaKuxA1G .error-icon{fill:#552222;}#mermaid-svg-XgEtuocdFaKuxA1G .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-XgEtuocdFaKuxA1G .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-XgEtuocdFaKuxA1G .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-XgEtuocdFaKuxA1G .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-XgEtuocdFaKuxA1G .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-XgEtuocdFaKuxA1G .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-XgEtuocdFaKuxA1G .marker{fill:#333333;stroke:#333333;}#mermaid-svg-XgEtuocdFaKuxA1G .marker.cross{stroke:#333333;}#mermaid-svg-XgEtuocdFaKuxA1G svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-XgEtuocdFaKuxA1G .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-XgEtuocdFaKuxA1G .cluster-label text{fill:#333;}#mermaid-svg-XgEtuocdFaKuxA1G .cluster-label span{color:#333;}#mermaid-svg-XgEtuocdFaKuxA1G .label text,#mermaid-svg-XgEtuocdFaKuxA1G span{fill:#333;color:#333;}#mermaid-svg-XgEtuocdFaKuxA1G .node rect,#mermaid-svg-XgEtuocdFaKuxA1G .node circle,#mermaid-svg-XgEtuocdFaKuxA1G .node ellipse,#mermaid-svg-XgEtuocdFaKuxA1G .node polygon,#mermaid-svg-XgEtuocdFaKuxA1G .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-XgEtuocdFaKuxA1G .node .label{text-align:center;}#mermaid-svg-XgEtuocdFaKuxA1G .node.clickable{cursor:pointer;}#mermaid-svg-XgEtuocdFaKuxA1G .arrowheadPath{fill:#333333;}#mermaid-svg-XgEtuocdFaKuxA1G .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-XgEtuocdFaKuxA1G .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-XgEtuocdFaKuxA1G .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-XgEtuocdFaKuxA1G .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-XgEtuocdFaKuxA1G .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-XgEtuocdFaKuxA1G .cluster text{fill:#333;}#mermaid-svg-XgEtuocdFaKuxA1G .cluster span{color:#333;}#mermaid-svg-XgEtuocdFaKuxA1G div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-XgEtuocdFaKuxA1G :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

字节缓冲输入流
字节缓冲输出流
字符缓冲输入流
字符输入转换流
字符缓冲输出流
字符输出转换流
IO流体系
字节流
字符流
InputStream-抽象类
FileInputStream-实现类
BufferedInputStream-实现类
OutputStream-抽象类
FileOutputStream-实现类
BufferedOutputStream-实现类
Reader-抽象类
FileReader-实现类
BufferedReader-实现类
InputStreamReader-实现类
Writer-抽象类
FileWriter-实现类
BufferedWriter-实现类
OutputStreamWriter-实现类

字符输入转换流:

  • InputStreamReader,可以把原始的字节流按照指定编码转换成字符输入流。
构造器 说明
public InputStreamReader(InputStream is0) 可以把原始的字节流按照代码默认编码转换成字符输入流。几乎不用,与默认的FileReader一样。
public InputStreamReader(InputStream is, String chartSet) 可以把原始的字节流按照指定编码转换成字符输入流,这样字符流中的字符就不乱码了。(重点)

InputStreamReaderDemo.java

import java.io.*;public class InputStreamReaderDemo {public static void main(String[] args) throws Exception {// 提取GBK文件的原始字节流InputStream inputStream = new FileInputStream("day11-oop-demo/src/gbkData.txt");// 把原始字节流以指定GBK编码转换成字符输入流Reader reader = new InputStreamReader(inputStream, "GBK");// 把低级的字符输入流包装成高级的缓冲字符输入流BufferedReader bufferedReader = new BufferedReader(reader);String line;while ((line = bufferedReader.readLine()) != null) {System.out.println(line);}}
}

总结:

  1. 字符输入转换流InputStreamReader作用:

    • 可以解决字符流读取不同编码乱码的问题。
    • public InputStreamReader(InputStream is, String charset) 可以指定编码把原始字节流转换成字符流,如此字符流中的字符不乱码。

c.字符输出转换流

  1. 如果需要控制写出去的字符使用的编码,怎么办?

    • 可以把字符以指定编码获取字节后再使用字节输出流写出去

      "我爱中国".getBytes(编码)
      
    • 可以使用字符输出转换流实现。

字符输出转换流:

  • 字符输出转换流:OutputStreamWriter,可以把字节输出流按照制定编码转换成字符输出流。
构造器 说明
public OutputStreamWriter(OutputStream os) 可以把原始的字节输出流按照代码默认编码转换成字符输出流,几乎不用。
public OutputStreamWriter(OutputStream os, String charset) 可以把原始的字节输出流按照指定编码转换成字符输出流(重点)。

OutputStreamWriterDemo.java

import java.io.*;public class OutputStreamWriterDemo {public static void main(String[] args) throws Exception {// 定义一个字节输出流OutputStream outputStream = new FileOutputStream("day11-oop-demo/src/gbkData.txt");// 把原始的字节输出流转换成字符输出流// 以默认的UTF-8写字符出去 跟直接用FileWriter一样// Writer writer = new OutputStreamWriter(outputStream);// 指定GBK编码写字符Writer writer = new OutputStreamWriter(outputStream, "GBK");// 把低级的缓冲输出流包装成高级的缓冲字符输出流BufferedWriter bufferedWriter = new BufferedWriter(writer);// 写入数据bufferedWriter.write("我爱中国,一");bufferedWriter.newLine();bufferedWriter.write("我爱中国,二");bufferedWriter.newLine();bufferedWriter.write("我爱中国,三");// 刷新bufferedWriter.flush();// 关闭流bufferedWriter.close();}
}

总结:

  1. 字符输出转换流OutputStreamWriter的作用?

    • public OutputStreamWriter(OutputStream os, String charset)
    • 可以指定编码把字节输出流转化成字符输出流,从而可以指定写出去的字符编码。

3.序列化对象

#mermaid-svg-L0SmUBm3H55O9Ym6 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-L0SmUBm3H55O9Ym6 .error-icon{fill:#552222;}#mermaid-svg-L0SmUBm3H55O9Ym6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-L0SmUBm3H55O9Ym6 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-L0SmUBm3H55O9Ym6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-L0SmUBm3H55O9Ym6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-L0SmUBm3H55O9Ym6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-L0SmUBm3H55O9Ym6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-L0SmUBm3H55O9Ym6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-L0SmUBm3H55O9Ym6 .marker.cross{stroke:#333333;}#mermaid-svg-L0SmUBm3H55O9Ym6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-L0SmUBm3H55O9Ym6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-L0SmUBm3H55O9Ym6 .cluster-label text{fill:#333;}#mermaid-svg-L0SmUBm3H55O9Ym6 .cluster-label span{color:#333;}#mermaid-svg-L0SmUBm3H55O9Ym6 .label text,#mermaid-svg-L0SmUBm3H55O9Ym6 span{fill:#333;color:#333;}#mermaid-svg-L0SmUBm3H55O9Ym6 .node rect,#mermaid-svg-L0SmUBm3H55O9Ym6 .node circle,#mermaid-svg-L0SmUBm3H55O9Ym6 .node ellipse,#mermaid-svg-L0SmUBm3H55O9Ym6 .node polygon,#mermaid-svg-L0SmUBm3H55O9Ym6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-L0SmUBm3H55O9Ym6 .node .label{text-align:center;}#mermaid-svg-L0SmUBm3H55O9Ym6 .node.clickable{cursor:pointer;}#mermaid-svg-L0SmUBm3H55O9Ym6 .arrowheadPath{fill:#333333;}#mermaid-svg-L0SmUBm3H55O9Ym6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-L0SmUBm3H55O9Ym6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-L0SmUBm3H55O9Ym6 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-L0SmUBm3H55O9Ym6 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-L0SmUBm3H55O9Ym6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-L0SmUBm3H55O9Ym6 .cluster text{fill:#333;}#mermaid-svg-L0SmUBm3H55O9Ym6 .cluster span{color:#333;}#mermaid-svg-L0SmUBm3H55O9Ym6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-L0SmUBm3H55O9Ym6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

字节缓冲输入流
对象字节输入流
字节缓冲输出流
对象字节输出流
字符缓冲输入流
字符输入转换流
字符缓冲输出流
字符输出转换流
IO流体系
字节流
字符流
InputStream-抽象类
FileInputStream-实现类
BufferedInputStream-实现类
ObjectInputStream-实现类
OutputStream-抽象类
FileOutputStream-实现类
BufferedOutputStream-实现类
ObjectOutputStream-实现类
Reader-抽象类
FileReader-实现类
BufferedReader-实现类
InputStreamReader-实现类
Writer-抽象类
FileWriter-实现类
BufferedWriter-实现类
OutputStreamWriter-实现类

a.对象序列化

对象序列化:

  • 作用:以内存为基准,把内存中的对象存储到磁盘文件中去,称为对象序列化。
  • 使用到的流是对象字节输出流:ObjectOutputStream。
#mermaid-svg-d5h9bdalCSKekZLG {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-d5h9bdalCSKekZLG .error-icon{fill:#552222;}#mermaid-svg-d5h9bdalCSKekZLG .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d5h9bdalCSKekZLG .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-d5h9bdalCSKekZLG .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d5h9bdalCSKekZLG .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d5h9bdalCSKekZLG .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d5h9bdalCSKekZLG .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d5h9bdalCSKekZLG .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d5h9bdalCSKekZLG .marker.cross{stroke:#333333;}#mermaid-svg-d5h9bdalCSKekZLG svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d5h9bdalCSKekZLG .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-d5h9bdalCSKekZLG .cluster-label text{fill:#333;}#mermaid-svg-d5h9bdalCSKekZLG .cluster-label span{color:#333;}#mermaid-svg-d5h9bdalCSKekZLG .label text,#mermaid-svg-d5h9bdalCSKekZLG span{fill:#333;color:#333;}#mermaid-svg-d5h9bdalCSKekZLG .node rect,#mermaid-svg-d5h9bdalCSKekZLG .node circle,#mermaid-svg-d5h9bdalCSKekZLG .node ellipse,#mermaid-svg-d5h9bdalCSKekZLG .node polygon,#mermaid-svg-d5h9bdalCSKekZLG .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-d5h9bdalCSKekZLG .node .label{text-align:center;}#mermaid-svg-d5h9bdalCSKekZLG .node.clickable{cursor:pointer;}#mermaid-svg-d5h9bdalCSKekZLG .arrowheadPath{fill:#333333;}#mermaid-svg-d5h9bdalCSKekZLG .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-d5h9bdalCSKekZLG .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-d5h9bdalCSKekZLG .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-d5h9bdalCSKekZLG .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-d5h9bdalCSKekZLG .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-d5h9bdalCSKekZLG .cluster text{fill:#333;}#mermaid-svg-d5h9bdalCSKekZLG .cluster span{color:#333;}#mermaid-svg-d5h9bdalCSKekZLG div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-d5h9bdalCSKekZLG :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

对象字节输出流,写对象数据到磁盘文件
内存
磁盘

对象序列化:

  • 使用到的流是对象字节输出流:ObjectOutputStream。
构造器 说明
public ObjectOutpuStream(OutputStream out) 把低级字节输出流包装成高级的对象字节输出流。
方法名称 说明
public final void writeObject(Object obj) 把对象写出去到对象序列化流的文件中去。

Student.java

import java.io.Serial;
import java.io.Serializable;/*** 对象如果要序列化 必须实现Serializable序列化接口*/
public class Student implements Serializable {// 申明序列化的版本号码// 序列化的版本号与反序列化的版本号必须一致才不会出错@Serialprivate static final long serialVersionUID = 1;private String name;private char sex;// transient修饰的成员变量不参与序列化private transient int age;public Student() {}public Student(String name, char sex, int age) {this.name = name;this.sex = sex;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public char getSex() {return sex;}public void setSex(char sex) {this.sex = sex;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", sex='" + sex + '\'' +", age='" + age + '\'' +'}';}
}

ObjectOutputStreamDemo.java

package com.javase.serializable;import java.io.FileOutputStream;
import java.io.ObjectOutputStream;/*** 目标:学会对象序列化,使用ObjectOutputStream把内存中的对象存入到磁盘文件中**/
public class ObjectOutputStreamDemo {public static void main(String[] args) throws Exception {// 创建学生对象Student student = new Student("花千骨", '女', 16);// 对象序列化:使用对象字节输出流包装字节输出流管道ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("day12-oop-demo/src/obj.txt"));// 直接调用序列化方法objectOutputStream.writeObject(student);// 释放资源objectOutputStream.close();}
}

b.对象反序列化

对象反序列化:

  • 使用到的流是对象字节输入流:ObjectInputStream。
  • 作用:以内存为基准,把存储到磁盘文件中去的对象数据恢复成内存中的对象,称为对象反序列化。
#mermaid-svg-91WQdiP4CEbnc2BO {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-91WQdiP4CEbnc2BO .error-icon{fill:#552222;}#mermaid-svg-91WQdiP4CEbnc2BO .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-91WQdiP4CEbnc2BO .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-91WQdiP4CEbnc2BO .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-91WQdiP4CEbnc2BO .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-91WQdiP4CEbnc2BO .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-91WQdiP4CEbnc2BO .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-91WQdiP4CEbnc2BO .marker{fill:#333333;stroke:#333333;}#mermaid-svg-91WQdiP4CEbnc2BO .marker.cross{stroke:#333333;}#mermaid-svg-91WQdiP4CEbnc2BO svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-91WQdiP4CEbnc2BO .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-91WQdiP4CEbnc2BO .cluster-label text{fill:#333;}#mermaid-svg-91WQdiP4CEbnc2BO .cluster-label span{color:#333;}#mermaid-svg-91WQdiP4CEbnc2BO .label text,#mermaid-svg-91WQdiP4CEbnc2BO span{fill:#333;color:#333;}#mermaid-svg-91WQdiP4CEbnc2BO .node rect,#mermaid-svg-91WQdiP4CEbnc2BO .node circle,#mermaid-svg-91WQdiP4CEbnc2BO .node ellipse,#mermaid-svg-91WQdiP4CEbnc2BO .node polygon,#mermaid-svg-91WQdiP4CEbnc2BO .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-91WQdiP4CEbnc2BO .node .label{text-align:center;}#mermaid-svg-91WQdiP4CEbnc2BO .node.clickable{cursor:pointer;}#mermaid-svg-91WQdiP4CEbnc2BO .arrowheadPath{fill:#333333;}#mermaid-svg-91WQdiP4CEbnc2BO .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-91WQdiP4CEbnc2BO .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-91WQdiP4CEbnc2BO .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-91WQdiP4CEbnc2BO .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-91WQdiP4CEbnc2BO .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-91WQdiP4CEbnc2BO .cluster text{fill:#333;}#mermaid-svg-91WQdiP4CEbnc2BO .cluster span{color:#333;}#mermaid-svg-91WQdiP4CEbnc2BO div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-91WQdiP4CEbnc2BO :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

对象字节输出流,写对象数据到磁盘文件
磁盘
内存
构造器 说明
public ObjectInputStream(InputStream out) 把低级字节输入流包装成高级的对象字节输入流。
方法名称 说明
public Object readObject() 把存储到磁盘文件中去的对象数据恢复成内存中的对象返回。

ObjectInputStreamDemo.java

import java.io.FileInputStream;
import java.io.ObjectInputStream;/*** 目标:学会进行对象反序列化 使用对象字节输入流把文件中的对象数据恢复成内存中的Java对象*/
public class ObjectInputStreamDemo {public static void main(String[] args) throws Exception{// 创建对象字节输入流管道包装低级的字节流输入流管道ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("day12-oop-demo/src/obj.txt"));// 调用字节输入流的反序列化方法Student student = (Student) objectInputStream.readObject();// 关闭流objectInputStream.close();System.out.println(student);}
}

4.打印流

#mermaid-svg-I9jezmhkD1LDTpbp {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-I9jezmhkD1LDTpbp .error-icon{fill:#552222;}#mermaid-svg-I9jezmhkD1LDTpbp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-I9jezmhkD1LDTpbp .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-I9jezmhkD1LDTpbp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-I9jezmhkD1LDTpbp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-I9jezmhkD1LDTpbp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-I9jezmhkD1LDTpbp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-I9jezmhkD1LDTpbp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-I9jezmhkD1LDTpbp .marker.cross{stroke:#333333;}#mermaid-svg-I9jezmhkD1LDTpbp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-I9jezmhkD1LDTpbp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-I9jezmhkD1LDTpbp .cluster-label text{fill:#333;}#mermaid-svg-I9jezmhkD1LDTpbp .cluster-label span{color:#333;}#mermaid-svg-I9jezmhkD1LDTpbp .label text,#mermaid-svg-I9jezmhkD1LDTpbp span{fill:#333;color:#333;}#mermaid-svg-I9jezmhkD1LDTpbp .node rect,#mermaid-svg-I9jezmhkD1LDTpbp .node circle,#mermaid-svg-I9jezmhkD1LDTpbp .node ellipse,#mermaid-svg-I9jezmhkD1LDTpbp .node polygon,#mermaid-svg-I9jezmhkD1LDTpbp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-I9jezmhkD1LDTpbp .node .label{text-align:center;}#mermaid-svg-I9jezmhkD1LDTpbp .node.clickable{cursor:pointer;}#mermaid-svg-I9jezmhkD1LDTpbp .arrowheadPath{fill:#333333;}#mermaid-svg-I9jezmhkD1LDTpbp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-I9jezmhkD1LDTpbp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-I9jezmhkD1LDTpbp .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-I9jezmhkD1LDTpbp .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-I9jezmhkD1LDTpbp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-I9jezmhkD1LDTpbp .cluster text{fill:#333;}#mermaid-svg-I9jezmhkD1LDTpbp .cluster span{color:#333;}#mermaid-svg-I9jezmhkD1LDTpbp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-I9jezmhkD1LDTpbp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

字节缓冲输入流
对象字节输入流
字节缓冲输出流
对象字节输出流
字节打印流
字符缓冲输入流
字符输入转换流
字符缓冲输出流
字符输出转换流
字符打印流
IO流体系
字节流
字符流
InputStream-抽象类
FileInputStream-实现类
BufferedInputStream-实现类
ObjectInputStream-实现类
OutputStream-抽象类
FileOutputStream-实现类
BufferedOutputStream-实现类
ObjectOutputStream-实现类
PrintStream-实现类
Reader-抽象类
FileReader-实现类
BufferedReader-实现类
InputStreamReader-实现类
Writer-抽象类
FileWriter-实现类
BufferedWriter-实现类
OutputStreamWriter-实现类
PrintWriter-实现类

打印流:

  • 作用:打印流可以实现方便、高效的打印数据到文件中去。打印流一般是指:PrintStream、PrintWriter两个类。
  • 可以实现打印什么数据就是什么数据,例如打印整数97写出去就是97,打印boolean的true,写出去就是true。

a.PrintStream、PrintWriter

PrintStream:

构造器 说明
public PrintStream(OutputStream os) 打印流直接通向字节输出流管道。
public PrintStream(File f) 打印流直接通向文件对象。
public PrintStream(String filepath) 打印流直接通向文件路径。

Test.java

import java.io.FileOutputStream;
import java.io.PrintStream;public class Test {public static void main(String[] args) throws Exception{// 创建一个打印流对象PrintStream printStream = new PrintStream("day12-oop-demo/src/printstream.txt");// 基于低级管道 追加写入// PrintStream printStream = new PrintStream(new FileOutputStream("day12-oop-demo/src/printstream.txt", true));// 指定字符编码格式// PrintStream printStream = new PrintStream("day12-oop-demo/src/printstream.txt", "GBK");printStream.println(1);printStream.println('a');printStream.println("我爱中国");printStream.println(true);printStream.println("打印流");// 关闭流printStream.close();}
}

PrintWriter:

构造器 说明
public PrintWriter(OutputStream os) 打印流直接通向字节输出流管道。
public PrintWriter(Writer w) 打印流直接通向字符输出流管道。
public PrintWriter(File f) 打印流直接通向文件对象。
public PrintWriter(String filepath) 打印流直接通向文件路径。
方法 说明
public void print(Xxx xx) 打印任意类型的数据出去。

Test.java

import java.io.PrintStream;
import java.io.PrintWriter;public class Test {public static void main(String[] args) throws Exception {// 创建一个打印流对象PrintWriter printWriter = new PrintWriter("day12-oop-demo/src/printWriter.txt");// PrintWriter printWriter = new PrintWriter("day12-oop-demo/src/printWriter.txt", "GBK");printWriter.println(1);printWriter.println('a');printWriter.println("我爱中国");printWriter.println(true);printWriter.println("打印流");// 关闭流printWriter.close();}
}

PrintStream和PrintWriter的区别:

  • 打印数据功能是一摸一样的,都是使用方便,性能高效(核心优势)。
  • PrintStream继承自字节输出流OutputStream,支持写字节数据的方法。
  • PrintWriter继承自字符输出流Writer,支持写字符数据出去。

总结:

  1. 打印流有几种?各有什么特点?

    • 打印流一般是指:PrintStream、PrintWriter两个类。
    • 打印功能两者是一样的使用方式。
    • PrintStream继承自字节输出流OutputStream,支持写字节。
    • PrintWrite继承自字符输出流Writer,支持写字符。
  2. 打印流的优势是什么?
    • 两者在打印功能上都是使用方便、性能高效(核心优势)。

b.输出语句的重定向

  • 属于打印流的一种应用,可以把输出语句的打印位置改到文件。

    PrintStream ps = new PrintStream("文件地址");System.setOUt(ps);
    

Test.java

import java.io.PrintStream;/*** 目标:了解改变输出语句的位置到文件*/
public class Test {public static void main(String[] args) throws Exception {System.out.println("        饮酒        ");System.out.println("采菊东篱下,悠然见南山。");System.out.println("山气日夕佳,飞鸟相与还。");// 改变输出语句的位置(重定向)// 创建一个打印流对象PrintStream printStream = new PrintStream("day12-oop-demo/src/打印流重定向.txt");// 把系统打印流改成我们自己的打印流System.setOut(printStream);System.out.println("      西江月·自幼曾攻经史      ");System.out.println("心在山东身在吴,飘蓬江海谩嗟吁。");System.out.println("他日若遂凌云志,敢笑黄巢不丈夫。");}
}

5.Properties

#mermaid-svg-tA65Yow8FuHT2l0H {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-tA65Yow8FuHT2l0H .error-icon{fill:#552222;}#mermaid-svg-tA65Yow8FuHT2l0H .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tA65Yow8FuHT2l0H .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-tA65Yow8FuHT2l0H .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tA65Yow8FuHT2l0H .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tA65Yow8FuHT2l0H .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tA65Yow8FuHT2l0H .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tA65Yow8FuHT2l0H .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tA65Yow8FuHT2l0H .marker.cross{stroke:#333333;}#mermaid-svg-tA65Yow8FuHT2l0H svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tA65Yow8FuHT2l0H .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-tA65Yow8FuHT2l0H .cluster-label text{fill:#333;}#mermaid-svg-tA65Yow8FuHT2l0H .cluster-label span{color:#333;}#mermaid-svg-tA65Yow8FuHT2l0H .label text,#mermaid-svg-tA65Yow8FuHT2l0H span{fill:#333;color:#333;}#mermaid-svg-tA65Yow8FuHT2l0H .node rect,#mermaid-svg-tA65Yow8FuHT2l0H .node circle,#mermaid-svg-tA65Yow8FuHT2l0H .node ellipse,#mermaid-svg-tA65Yow8FuHT2l0H .node polygon,#mermaid-svg-tA65Yow8FuHT2l0H .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tA65Yow8FuHT2l0H .node .label{text-align:center;}#mermaid-svg-tA65Yow8FuHT2l0H .node.clickable{cursor:pointer;}#mermaid-svg-tA65Yow8FuHT2l0H .arrowheadPath{fill:#333333;}#mermaid-svg-tA65Yow8FuHT2l0H .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tA65Yow8FuHT2l0H .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tA65Yow8FuHT2l0H .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-tA65Yow8FuHT2l0H .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-tA65Yow8FuHT2l0H .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tA65Yow8FuHT2l0H .cluster text{fill:#333;}#mermaid-svg-tA65Yow8FuHT2l0H .cluster span{color:#333;}#mermaid-svg-tA65Yow8FuHT2l0H div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tA65Yow8FuHT2l0H :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}

Map 接口
HashMap 实现类
HashTable 实现类
... 接口
LinkedHashMap 实现类
Properties 实现类
TreeMap 实现类

Properties属性集对象:

  • 其实就是一个Map集合,但是我们一般不会当集合使用,因为HashMap更好用。

Properties核心作用:

  • Properties代表的是一个属性文件,可以把自己对象中的键值对信息存入到一个属性文件中去。
  • 属性文件:后缀是.properties结尾的文件,里面的内容都是key=value,后续做系统配置信息的。

Properties的API:

  • Properties和IO流结合的方法:

    构造器 说明
    void load(InputStream isStream) 从输入字节流读取属性列表(键和元素对)。
    void load(Reader reader) 从输入字节流读取属性列表(键和元素对)。
    void store(OutputStream out, String comments) 将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InputStream)方法的格式写入输出字节流。
    void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此Properites表中,以适合使用load(Reader)方法的格式写入输出字节流。
    public Object setProperty(String key, String value) 保持键值对(put)。
    public String getProperty(String key) 使用此属性列表中指定的键搜索属于值(get)。
    public Set stringPropertyNames() 所有键的名称的集合(keySet())。

PropertiesDemo.java

import java.io.FileReader;
import java.io.FileWriter;
import java.util.Map;
import java.util.Properties;public class PropertiesDemo {public static void main(String[] args) throws Exception{Properties properties = new Properties();// 存储键值对properties.put("admin", "123456");properties.setProperty("lucy", "666666");System.out.println(properties);// 存储到文件 此流不用关闭properties.store(new FileWriter("day12-oop-demo/src/users.properties"), "注释");// 加载属性文件中的键值对数据到属性对象properties中去properties.load(new FileReader("day12-oop-demo/src/users.properties"));System.out.println(properties);// 取出键对应的值String admin = properties.getProperty("admin");System.out.println(admin);}
}

6.IO框架

commons-io框架:

  • commons-io是apache开源基金组织提供的一组有关IO操作的类库,可以提高IO功能开发的效率。
  • commons-io工具包提供了很多有关IO操作的类,有两个主要的类FileUtils、IOUtils。

FileUtils主要有如下方法:

方法名 说明
String readFileToString(File file, String encoding) 读取文件中的数据,返回字符串。
void copyFile(File srcFile, File destFile) 复制文件。
void copyDirectoryToDirectory(File srcDir, File destDir) 复制文件夹。

导入commons-io-2.11.0做开发

需求:

  • 使用commons-io简化io流读写。

分析:

  1. 在项目中创建一个文件夹:lib。
  2. 将commons-io-2.11.0.jar文件复制到lib文件夹。
  3. 在jar文件上点击右键,选择Add as Library -> 点击 OK。
  4. 在类中导包使用。

Test.java

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;public class Test {public static void main(String[] args) throws Exception {// 1.文件复制IOUtils.copy(new FileInputStream("day12-oop-demo/src/obj.txt"), new FileOutputStream("day12-oop-demo/src/objNew.txt"));// 2.文件复制到某个文件夹下FileUtils.copyFileToDirectory(new File("day12-oop-demo/src/obj.txt"), new File("day12-oop-demo/src/commonsiodemo/"));// 3.文件夹复制到某个文件夹下FileUtils.copyDirectoryToDirectory(new File("day12-oop-demo/src/commonsiodemo/"), new File("day12-oop-demo/src/commonsiodemoNew/"));// 4.删除文件夹FileUtils.deleteDirectory(new File("day12-oop-demo/src/commonsiodemoNew/"));// JDK 1.7 也做了一些一行代码完成复制的操作:NIOFiles.copy(Path.of("day12-oop-demo/src/commonsiodemo/"), Path.of("day12-oop-demo/src/commonsiodemoNIO/"));}
}
       |

导入commons-io-2.11.0做开发

需求:

  • 使用commons-io简化io流读写。

分析:

  1. 在项目中创建一个文件夹:lib。
  2. 将commons-io-2.11.0.jar文件复制到lib文件夹。
  3. 在jar文件上点击右键,选择Add as Library -> 点击 OK。
  4. 在类中导包使用。

Test.java

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;public class Test {public static void main(String[] args) throws Exception {// 1.文件复制IOUtils.copy(new FileInputStream("day12-oop-demo/src/obj.txt"), new FileOutputStream("day12-oop-demo/src/objNew.txt"));// 2.文件复制到某个文件夹下FileUtils.copyFileToDirectory(new File("day12-oop-demo/src/obj.txt"), new File("day12-oop-demo/src/commonsiodemo/"));// 3.文件夹复制到某个文件夹下FileUtils.copyDirectoryToDirectory(new File("day12-oop-demo/src/commonsiodemo/"), new File("day12-oop-demo/src/commonsiodemoNew/"));// 4.删除文件夹FileUtils.deleteDirectory(new File("day12-oop-demo/src/commonsiodemoNew/"));// JDK 1.7 也做了一些一行代码完成复制的操作:NIOFiles.copy(Path.of("day12-oop-demo/src/commonsiodemo/"), Path.of("day12-oop-demo/src/commonsiodemoNIO/"));}
}

Java进阶(十一)缓冲流相关推荐

  1. java day21【缓冲流、转换流、序列化流】

    第一章 缓冲流 昨天学习了基本的一些流,作为IO流的入门,今天我们要见识一些更强大的流.比如能够高效读写的缓冲流,能够转换编码的转换流,能够持久化存储对象的序列化流等等.这些功能更为强大的流,都是在基 ...

  2. JAVA学习 API_day10(缓冲流, 打印流, 对象流)

    缓冲流, 转换流, 打印流, 对象流 1. 缓冲流 1. 字节缓冲流 2. 字符缓冲流 2.打印流 1.字节打印流(了解) 2.字符打印流 3.对象流 1. 缓冲流 1. 字节缓冲流 包装 -> ...

  3. 黑马JAVA P163 字节缓冲流的性能分析

    package com.itheima.d2_byte_buffer_time;import java.io.*;public class ByteBufferTimeDemo {private st ...

  4. Java基础之——缓冲流、转换流、序列化流、打印流

    缓冲流.转换流.序列化流 1.缓冲流 见识一些更强大的流.比如能够高效读写的缓冲流,能够转换编码的转换流,能够持久化存储对象的序列化流等等.这些功能更为强大的流,都是在基本的流对象基础之上创建而来的, ...

  5. Java基础:缓冲流

    了解了IO流,再说一说一些更强大的流.比如能够高效读写的缓冲流,能够转换编码的转换流,能够持久化存储对象的序列化流等等.这些功能更为强大的流,都是在基本的流对象基础之上创建而来的,就像穿上铠甲的武士一 ...

  6. 黑马程序员-Java教程-10缓冲流、转换流、序列化流

    day10[缓冲流.转换流.序列化流.打印流] 主要内容 缓冲流 转换流 序列化流 打印流 教学目标 能够使用字节缓冲流读取数据到程序 能够使用字节缓冲流写出数据到文件 能够明确字符缓冲流的作用和基本 ...

  7. 【java笔记】缓冲流

    BufferedInputStream:字节缓冲输入流 BufferedOutputStream:字节缓冲输出流 BufferedWriter:字符缓冲输出流 BufferedReader:字符缓冲输 ...

  8. [Java基础]字节缓冲流

    字节缓冲输出流: package InstreamPack;import java.io.BufferedOutputStream; import java.io.FileNotFoundExcept ...

  9. java缓存流速度与硬盘_系统学习 Java IO (九)----缓冲流 BufferedInputStream/BufferedOutputStream...

    BufferedInputStream BufferedInputStream 类为输入流提供缓冲. 缓冲可以加快IO的速度. BufferedInputStream 不是一次从网络或磁盘读取一个字节 ...

  10. [Java基础]字符缓冲流

    代码如下: package CopyJavaPack01;import java.io.BufferedWriter; import java.io.FileWriter; import java.i ...

最新文章

  1. !--处理:借款冲销不自动冲减预算--
  2. iPhone 查看万能钥匙连接的 WiFi 密码
  3. python qt信号在qml 的使用_QML使用Python的函数过程解析
  4. 观察者模式(发布--订阅模式)
  5. 数据分析与挖掘中常用Python库的介绍与实践案例
  6. Maxim推出上/下变频SiGe混频器MAX2042
  7. 软考必备资料大放送,全科目软考资料都给你备好了!
  8. SpringBoot整合WebService实例
  9. AGV机器人核心部件——驱动轮
  10. 漫画:程序员找工作—外包公司
  11. 面试了一位 阿里出来的46 岁的程序员,思绪万千,最后结局居然...
  12. 前端——HTML,CSS
  13. 英读廊——为什么说密码中加入特殊字符会更安全?
  14. redis 常用命令
  15. java 集合交集、并集、差集、补集
  16. 浏览器的浏览模式——兼容模式
  17. 中科物栖CEO张磊:“芯片+OS”范式在万物互联时代的机遇与挑战|量子位·视点分享回顾...
  18. OGNL表达式的使用方法
  19. 下面对C语言的特点说法不正确的是,C语言程序设计基础试题及答案
  20. 经纬度坐标转平面直角坐标——高斯投影python/c#实现

热门文章

  1. 亚商投资顾问 早餐FM/1227加大医疗资源建设
  2. VR虚拟现实技术行业应用范围
  3. MYSQL索引使用技巧及注意事项
  4. 华硕主板B85-PRO GAMER关机后鼠标、键盘仍亮着问题的解决办法
  5. 计算机组成位模式,Pentium的工作模式-计算机组成原理与汇编语言-电子发烧友网站...
  6. storm多个bolt之间多对一或一对多下发
  7. 前端架构师的相关体系内容
  8. 无迹(损)卡尔曼滤波(UKF)理论讲解与实例
  9. LTE学习:PCFICH信道总结
  10. Myeclipse 手动安装Velocity插件