Skip to content

第五章 Stream流与IO流 v1.0 ​

第一部分 Stream流 ​

一、获取Stream流对象 ​

1.数组 ​

java
//通过数组工具类
Stream<泛型> 对象名 = Arrays.stream(array);
//通过Stream类
Stream<泛型> 对象名 = Stream.of(array);

2.Collection类 ​

java
Stream<泛型> 对象名 = list.stream();

3.Map类 ​

java
//获取键的Stream流
Stream<泛型> 对象名 = map.keySet.stream();
//获取值的Stream流
Stream<泛型> 对象名 = map.values.stream();
//获取键值对(整体)的Stream流
Stream<Map.Entry<泛型, 泛型>> 对象名 = map.entrySet.stream();

二、操作Stream流 ​

用于简化集合和数组操作的API。

1.常用中间操作(非终结)方法 ​

中间操作方法调用完成后返回新的Stream流可以继续使用,支持链式编程

2.常见终结操作方法 ​

3.使用方法引用进行操作 ​

java
list.stream().map(Student::new).forEach(System.out::println);  //构造对象并遍历

三、收集Stream流 ​

将操作完成的Stream流转为集合或数组对象,要注意:流只能使用一次,收集一次之后无法再次收集

收集Stream流的方法 ​

java
//收集为集合类对象
集合类型名<泛型> 对象名 = s.collect(Collectors.方法名());  //常用收集方法:toSet,toList,toMap
//收集为数组
Object[] 对象名 = s.toArray();  //流中数据类型不确定,一般用Object类型
//String[] 对象名 = s.toArray(String[]::new);  //例:转为String类型数组,一般不使用

第二部分 基础IO流 ​

一、File类 ​

File类代表操作系统的文件对象,提供了诸如:定位文件,获取文件信息、删除文件、创建文件等功能。

1.Java文件路径 ​

File类支持绝对路径与相对路径,一般相对路径对应到所创建工程的根目录(作为.目录)

bash
|-project  #视为当前目录
  ├─module  #./module
    ├─src  #./module/src/main
       ├─main  #./module/src/main
       │  ├─java  #./module/src/main/java
       │  └─resources  #./module/src/main/resources
       └─test  #./module/src/test
           └─java  #./module/src/test/java

2.创建File类对象 ​

常用File类构造方法

  1. File(String path):根据文件路径创建文件对象
  2. File(String parent, String child):根据父路径和子文件路径创建文件对象
  3. File(File parent, String child):根据父文件对象和子文件路径创建文件对象

3.常见方法 ​

a.文件信息获取 ​
b.创建与删除文件 ​

二、IO流概述 ​

代表任何有能力产出数据的数据源对象或是接受数据的接收端对象,用于数据传输、读写数据

1.IO流分类 ​

  • 字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流
  • 字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流
  • 字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流
  • 字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流

2.字符集 ​

a.ASCII字符集 ​

包括数字、英文、符号,ASCI使用一个字节存储一个字符,总共可以表示128个字符信息

b.GBK字符集 ​

window系统默认的码表,兼容ASCII码表,也包含了几万个汉字,并支持繁体汉字以及部分日韩文字。

GBK是中国的码表,一个中文以两个字节的形式存储,但不包含世界上所有国家的文字。

c.Unicode字符集 ​

Unicode(又称统一码、 万国码、单一码)是计算机科学领域里的一项业界字符编码标准,常见的为UTF-8​

Unicode容纳世界上大多数国家的所有常见文字和符号,以UTF-8编码后一个中文一般以三个字节的形式存储

d.关于字符长度 ​
  • 英文和数字等在任何国家的字符集中都占1个字节
  • GBK字符中一个中文字符占2个字节
  • UTF-8编码中一个中文一般占3个字节

3.字符串的编码与解码 ​

字符串编码:byte[] bytes = s.getBytes("字符集")

字符串解码:String s = String(byte[] bytes, "字符集")

三、字节流 ​

1.文件字节输入流(FileInputStream) ​

a.常见构造方法 ​
  1. FileInputStream(File file):根据文件对象创建文件字节输入流
  2. FileInputStream(String path):根据文件路径创建文件字节输入流
b.读取文件内容方法 ​
  1. read():每次读取一个字节返回,如果字节已经没有可读的返回-1
  2. read(byte[] b):每次读取一个字节数组,返回读取到的字节数组长度,读取完毕返回-1
c.示例 ​
java
try(InputStream is = new FileInputStream(StaticConfig.getPngFile())){
    //每次读取一个字节返回,如果字节已经没有可读的返回-1
    int aByte=is.read();
    //每次读取一个字节数组,返回读取到的字节数组长度,读取完毕返回-1
    byte[] b=new byte[100];
    int statusCode=is.read(b);
    System.out.println(aByte);  //输出:137(此时是int类型)
	System.out.println((byte)aByte);  //输出:-119(此时为byte类型,但byte类型是有符号的)
}catch (IOException e){
    e.printStackTrace();
}

try(InputStream is = new FileInputStream(StaticConfig.getPngFile())){
    //每次读取一个字节数组,返回读取到的字节数组长度,读取完毕返回-1
    byte[] b=new byte[100];
    int statusCode=is.read(b);
    System.out.println(b[0]);  //输出:-119
}catch (IOException e){
    e.printStackTrace();
}

2.文件字节输出流(FileOutputStream) ​

a.常见构造方法 ​
  1. FileOutputStream(File file):根据文件对象创建文件字节输出流
  2. FileOutputStream(String path):根据文件路径创建文件字节输出流
  3. FileOutputStream(File file, boolean append):根据文件对象创建追加数据的文件字节输出流
  4. FileOutputStream(String path, boolean append):根据文件路径创建追加数据的文件字节输出流
b.写入文件内容的方法 ​
  1. write(int b):将指定的字符写入文件中
  2. write(byte[] b):将字节流写入文件中
  3. flush():刷新缓存,立即写入

3.示例:使用字节流复制图片 ​

java
try {
    // 创建输入流和输出流
    InputStream inputStream = new FileInputStream("source.jpg");
    OutputStream outputStream = new FileOutputStream("destination.jpg");

    // 创建缓冲区
    byte[] buffer = new byte[1024];
    int bytesRead;

    // 从输入流读取数据,并写入到输出流中
    while ((bytesRead = inputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, bytesRead);
    }

    // 关闭输入流和输出流
    inputStream.close();
    outputStream.close();

    System.out.println("图片复制完成!");
} catch (IOException e) {
    e.printStackTrace();
}

4.释放资源 ​

输入输出流在使用完毕之后需要对有限的操作系统资源进行释放,否则会导致系统资源被耗尽

a.常规方式(手动释放资源) ​

在异常处理时提供finally块来执行所有清除操作,比如说IO流中的释放资源

java
OutputStream fos = null;
try {
    fos = new FileOutputStream("文件名");
    // 相关文件操作
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (fos != null) {
        fos.close();
    }
}
b.自动释放资源(JDK7引入) ​
java
try (OutputStream fos = new FileOutputStream("文件名")) {  //定义流对象
    // 相关文件操作
} catch (IOException e) {
    e.printStackTrace();
}

四、字符流 ​

1.文件字符输入流(FileReader) ​

a.常见构造方法 ​
  1. FileReader(File file):根据文件对象创建文件字符输入流
  2. FileReader(String path):根据文件路径创建文件字符输入流
b.读取文件内容的方法 ​
  1. read():每次读取一个字符的编号返回,如果字节已经没有可读的返回-1
  2. read(char[] b):每次读取一个字符数组,返回读取到的字符数组长度,读取完毕返回-1
java
try(
    Reader file=new FileReader("文件名");  //在此处声明的资源使用完毕会自动释放
) {
    char[] buffer = new char[1024];
    int len;
    while ((len = file.read(buffer)) != -1) {
        String rs = new String(buffer, 0, len);
        System.out.print(rs);
    }
} catch (IOException e){
    e.printStackTrace();
}

2.文件字符输出流(FileWriter) ​

a.常见构造方法 ​
  1. FileWriter(File file):根据文件对象创建文件字符输出流
  2. FileWriter(String path):根据文件路径创建文件字符输出流
  3. FileWriter(File file, boolean append):根据文件对象创建追加数据的文件字符输出流
  4. FileWriter(String path, boolean append):根据文件路径创建追加数据的文件字符输出流
b.写入文件内容的方法 ​
  1. write(int b):将指定的字符写入文件中
  2. write(char[] b):将字符流写入文件中
  3. write(String str):将字符串写入文件中
java
try(Writer file=new FileWriter("文件名", true)) {  //以追加模式打开文件
    file.write("写入文本信息\n")
}catch (IOException e){
    e.printStackTrace();
}

第三部分 高级IO流 ​

一、缓冲流 ​

缓冲流自带(8KB)缓冲区、可以提高原始字节流、字符流读写数据的性能,读写数据的性能更好

1.字节缓冲输入流(BufferedInputStream) ​

构造方法:BufferedInputStream(InputStream is)

2.字节缓冲输出流(BufferedOutputStream) ​

构造方法:BufferedOutputStream(InputStream os)

3.字符缓冲输入流(BufferedReader) ​

构造方法:BufferedReader(Reader fr)

独有成员方法:readLine():读取一行数据返回字符串,如果读取没有完毕,无行可读返回null

4.字符缓冲输出流(BufferedWriter) ​

构造方法:BufferedWriter(Writer fw)

独有成员方法:newLine():实现换行功能

二、转换流 ​

用于文件字符编码与代码指定编码不一致等情况下转化

1.字符输入转换流(InputStreamReader) ​

构造方法:InputStreamReader(InputStream is, String charset);

2.字符输出转换流(OutputStreamWriter) ​

构造方法:OutputStreamReader(OutputStream os, String charset);

三、序列化 ​

用于将Java对象进行长久化保存

1.序列化对象前提条件 ​

待序列化的对象实现了Serializable序列化接口

2.对象序列化(对象字节输出流,ObjectOutputStream) ​

以内存为基准,把内存中的对象存储到磁盘文件中去,称为对象序列化。

构造方法:ObjectOutputStream(OutputStream os):把低级字节输出流包装成高级的对象字节输出流

序列化对象使用方法:writeObject(Object o) //将内存中对象存储到磁盘文件

3.对象反序列化(对象字节输入流,ObjectInputStream) ​

以内存为基准,把存储到磁盘文件中去的对象数据恢复成内存中的对象,称为对象反序列化。

构造方法:ObjectInputStream(InputStream is);:把低级字节输入流包装成高级的对象字节输入流

反序列化对象使用方法:readObject(Object o) //将存储到磁盘文件中的对象重新读取到内存中

4.序列化过程中的敏感信息处理 ​

可以使用transient标记成员变量使之不参与序列化

java
public class Student implements Serializable {
    private String name;
    private String loginName;
    private transient String passWord;  //此字段不参与序列化,不会保存
    ...
}

5.序列化版本号 ​

待序列化对象中可以定义成员变量:private static final Long serialVersionUID = <版本号>;

当使用序列化版本号时,序列化的版本号与反序列化的版本号必须一致才不会出错

四、打印流 ​

使用方便且性能高效(底层通过缓冲流实现)的输出流,打印输出在控制台是什么数据,输出流中就是什么数据

打印功能(类似System.out)PrintStream与PrintWriter基本没有区别,只在写数据存在区别(但是基本不会使用)

1.字节打印流(PrintStream) ​

常用构造方法:

  1. PrintStream(OutputStream os):打印流直接通向字节输出流管道
  2. PrintStream(File f):打印流直接通向文件对象
  3. PrintStream(String filepath):打印流直接通向文件路径

2.字符打印流(PrintWriter) ​

常见构造方法:

  1. PrintWriter(OutputStream os):打印流直接通向字节输出流管道
  2. PrintWriter(Writer w):打印流直接通向字符输出流管道
  3. PrintWriter(File f):打印流直接通向文件对象
  4. PrintWriter(String filepath):打印流直接通向文件路径

3.System.out输出原理 ​

实际上System.out对应的是一个默认的PrintStream对象,默认将输出打印到控制台中

java
PrintStream ps = new PrintStream("文件名");
System.setOut(ps);  //把系统打印流改成我们自己的打印流
//此后System.out输出语句输出的内容即从控制台修改为对应文件

五、Properties ​

1.Properties简介 ​

属于Map集合体系,代表的是一个属性文件,可以把自己对象中的键值对信息存入到一个属性文件中去。

属性文件:后缀是.properties结尾的文件,里面的内容都是键值对,常用于进行系统信息配置。

2.常用方法 ​

a.操作属性 ​

setProperties(String key, String value):保存属性键值对到该Properties对象(对应keySet())

getProperties(String key):使用此属性列表中指定的键搜索属性值(对应get())

stringPropertyNames():获取所有键的名称的集合(对应keySet())

b.保存属性键值对到流 ​

load(InputStream iStream):从输入字节流读取属性列表(键和元素对)

load(Reader reader):从输入字符流读取属性列表(键和元素对)

c.从流读取属性键值对 ​

store(OutputStream oStream, String comments):将属性列表(键和元素对)写入该Properties对象

store(Writer writer, String comments):将属性列表(键和元素对)写入该Properties对象

六、IO框架(commons-io) ​

1.FileUtils ​

image.png

2.IOUtils ​

暂略