Stream流
Stream流的三类方法
- 获取Stream流创建一条流水线,并把数据放到流水线上准备进行操作
- 中间方法流水线上的操作。一次操作完毕之后,还可以继续进行其他操作。
- 终结方法一个Stream流只能有一个终结方法是流水线上的最后一个操作
Stream流的获取方法
- 单列集合
- 可以使用Collection接口中的默认方法stream()生成流
- default Stream stream()
- 双列集合
- 间接的生成流
- 可以先通过keySet或者entrySet获取一个Set集合,再获取Stream流
- 数组Arrays中的静态方法stream 生成流
- 同种数据类型的多个数据1,2,3,4,5….“aaa”,“bbb”,“ccc”….使用Stream.of(T…values)生成流
Stream流的常见中间操作方法
- Stream filter(Predicate predicate):用于对流中的数据进行过滤
- Predicate接口中的方法
- boolean test(T t):对给定的参数进行判断,返回一个布尔值
- Stream limit(long maxSize):截取指定参数个数的数据
- Stream skip(long n):跳过指定参数个数的数据
- static Stream concat(Stream a, Stream b):合并a和b两个流为一个流
- Stream distinct():去除流中重复的元素。依赖(hashCode和equals方法)
Stream流的常见终结操作方法
- void forEach(Consumer action):对此流的每个元素执行操作
- Consumer接口中的方法 void accept(T t):对给定的参数执行此操作
- long count():返回此流中的元素数
Stream流的收集操作
Stream流的收集方法
- R collect(Collector collector)
工具类Collectors提供了具体的收集方式
- public static Collector toList():把元素收集到List集合中
- public static Collector toSet():把元素收集到Set集合中
- public static Collector toMap(Function keyMapper,Function valueMapper):把元素收集到Map集合中
File类
IO就可以对硬盘中的文件进行读写
File表示要读写的文件在哪,也可以对文件进行创建,删除等操作
File类概述和构造方法
File:它是文件和目录路径名的抽象表示
- 文件和目录可以通过File封装成对象
- File封装的对象仅仅是一个路径名。它可以是存在的,也可以是不存在的。
File(String pathname)通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例
File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例
File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例
绝对路径和相对路径
- 绝对路径:从盘符开始
- 相对路径:相对当前项目下的路径
File类创建功能
public boolean createNewFile() 创建一个新的空的文件
public boolean mkdir() 创建一个单级文件夹
public boolean mkdirs() 创建一个多级文件夹
File类删除功能
public boolean delete() 删除由此抽象路径名表示的文件或目录
删除目录时的注意事项:
- delete方法直接删除不走回收站。
- 如果删除的是一个文件,直接删除。
- 如果删除的是一个文件夹,需要先删除文件夹中的内容,最后才能删除文件夹。
File类判断和获取功能
public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
public boolean isFile() 测试此抽象路径名表示的File是否为文件
public boolean exists() 测试此抽象路径名表示的File是否存在
public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
public String getPath() 将此抽象路径名转换为路径名字符串
public String getName() 返回由此抽象路径名表示的文件或目录的名称
File类高级获取功能
public File[] listFiles() 返回此抽象路径名表示的目录中的文件和目录的File对象数组
listFiles方法注意事项:
- 当调用者不存在时,返回null
- 当调用者是一个文件时,返回null
- 当调用者是一个空文件夹时,返回一个长度为0的数组
- 当调用者是一个有内容的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回
- 当调用者是一个有隐藏文件的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏内容
- 当调用者是一个需要权限才能进入的文件夹时,返回null
IO流
I表示intput,是数据从硬盘进内存的过程,称之为读。
O表示output,是数据从内存到硬盘的过程。称之为写。
字节流
字节流写数据
- 创建字节输出流对象。如果文件不存在,就创建。如果文件存在就清空。如果不想被清空则加true
- 写数据.写出的整数,实际写出的是整数在码表上对应的字母。可以写一个字节,写一个字节数组,写一个字节数组的一部分写一个回车换行:\r\n
- 释放资源.每次使用完流必须要释放资源。
字节流写数据的3种方式
void write(int b) 一次写一个字节数据
void write(byte[] b) 一次写一个字节数组数据
void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据
字节流写数据实现换行
写完数据后,加换行符windows:\r\n linux:\n
字节流写数据实现追加写入
- public FileOutputStream(String name,boolean append)
- 创建文件输出流以指定的名称写入文件。如果第二个参数为true ,不会清空文件里面的内容
字节流写数据加try…catch异常处理
异常处理标准格式:try….catch…finally
字节流读数据(一次读一个字节)
- 创建字节输入流对象。如果文件不存在,就直接报错。
- 读数据.读出来的是文件中数据的码表值。 a → 97
- 释放资源.每次使用完流必须要释放资源。
提高拷贝速度的解决方案:为了解决速度问题,字节流通过创建字节数组,可以一次读写多个数据。
一次读一个字节数组的方法:
- public int read(byte[] b):从输入流读取最多b.length个字节的数据
- 返回的是读入缓冲区的总字节数,也就是实际的读取字节个数
字节流缓冲流
字节缓冲流:
- BufferOutputStream:缓冲输出流
- BufferedInputStream:缓冲输入流
构造方法:
- 字节缓冲输出流:BufferedOutputStream(OutputStream out)
- 字节缓冲输入流:BufferedInputStream(InputStream in)
为什么构造方法需要的是字节流,而不是具体的文件或者路径呢?
- 字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作
字符流
把文件中的数据读取到内存时,如果此时文件中出现了中文,那么字节流就会出现乱码现象。所以纯文本的文件,我们就需要使用字符流来进行操作。
编码表
-
计算机中储存的信息都是用二进制数表示的;我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果
-
按照某种规则,将字符存储到计算机中,称为编码。
-
按照同样的规则,将存储在计算机中的二进制数解析显示出来,称为解码 。
-
编码和解码的方式必须一致,否则会导致乱码。
-
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码):包括了数字,大小写字符和一些常见的标点符号。注意:ASCII码表中是没有中文的。
-
GBK:window系统默认的码表。兼容ASCII码表,也包含了21003个汉字,并支持繁体汉字以及部分日韩文字。注意:GBK是中国的码表,一个中文以两个字节的形式存储。但不包含世界上所有国家的文字。
Unicode码表:由国际组织ISO 制定,是统一的万国码,计算机科学领域里的一项业界标准,容纳世界上大多数国家的所有常见文字和符号。但是因为表示的字符太多,所以Unicode码表中的数字不是直接以二进制的形式存储到计算机的,会先通过UTF-7,UTF-7.5,UTF-8,UTF-16,以及 UTF-32的编码方式再存储到计算机,其中最为常见的就是UTF-8。注意: Unicode是万国码,以UTF-8编码后一个中文以三个字节的形式存储
字符串中的编码解码问题
编码:
- byte[] getBytes():使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中
- byte[] getBytes(String charsetName):使用指定的字符集将该 String编码为一系列字节,将结果存储到新的字节数组中
解码:
- String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的 String
- String(byte[] bytes, String charsetName):通过指定的字符集解码指定的字节数组来构造新的 String
字符流读取中文的过程
-
字符流 = 字节流 + 编码表
基础知识:不管是在哪张码表中,中文的第一个字节一定是负数。 -
想要进行拷贝,一律使用字节流或者字节缓冲流
-
想要把文件中的数据读到内存中打印或者读到内存中运算,请使用字符输入流。想要把集合,数组,键盘录入等数据写到文件中,请使用字符输出流
-
GBK码表一个中文两个字节,UTF-8编码格式一个中文3个字节。
字符流写数据
- 创建字符输出流对象。如果文件不存在,就创建。但是要保证父级路径存在。如果文件存在就清空。
- 写数据.写出int类型的整数,实际写出的是整数在码表上对应的字母。写出字符串数据,是把字符串本身原样写出。
- 释放资源.每次使用完流必须要释放资源。
字符流写数据的5种方式
void write(int c) 写一个字符
void write(char[] cbuf) 写入一个字符数组
void write(char[] cbuf, int off, int len) 写入字符数组的一部分
void write(String str) 写一个字符串
void write(String str, int off, int len) 写一个字符串的一部分
flush() 刷新流,还可以继续写数据
close()关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
字符流读数据的2种方式
int read() 一次读一个字符数据
int read(char[] cbuf) 一次读一个字符数组数据
字符缓冲流
- BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可
以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途 - BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定
缓冲区大小,或者可以使用默认大小。 默认值足够大,可用于大多数用途
构造方法: - BufferedWriter(Writer out)
- BufferedReader(Reader in)
字符缓冲流特有功能
BufferedWriter:
- void newLine():写一行行分隔符,行分隔符字符串由系统属性定义
- BufferedReader:
- public String readLine() :读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为null
复制文件的异常处理
- 基本做法: try{可能出现异常的代码;}catch(异常类名 变量名){异常的处理代码;}finally{执行所有清除操作;}手动释放资源
- JDK7改进方案: try(定义流对象){可能出现异常的代码;}catch(异常类名 变量名){异常的处理代码;}自动释放资源
- JDK9改进方案:定义输入流对象;定义输出流对象;try(输入流对象;输出流对象){可能出现异常的代码;}catch(异常类名 变量名){异常的处理代码;}自动释放资源
转换流
转换流就是来进行字节流和字符流之间转换的
- OutputStreamWriter是从字符流到字节流的桥梁
- InputStreamReader是从字节流到字符流的桥梁
转换流的使用场景在JDK11之前,指定编码读写
对象操作流
可以把对象以字节的形式写到本地文件,直接打开文件,是读不懂的,需要再次用对象操作流读到内存中。
- 对象操作流分为两类:对象操作输入流和对象操作输出流
- 对象操作输出流(对象序列化流):就是将对象写到本地文件中,或者在网络中传输对象
- 对象操作输入流(对象反序列化流):把写到本地文件中的对象读到内存中,或者接收网络中传输的对象
用对象序列化流序列化了一个对象后,假如我们修改了对象所属的Javabean类,读取数据会不会出问题呢?
- 会出问题,会抛出InvalidClassException异常
- 解决: 给对象所属的类加一个serialVersionUIDprivate static final long serialVersionUID = 42L;
- 如果一个对象中的某个成员变量的值不想被序列化,实现方法
- 给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
Properties
- 是一个Map体系的集合类
- Properties中有跟IO相关的方法
- 只存字符串
Properties作为集合的特有方法:
Object setProperty(String key, String value) 设置集合的键和值,都是String类型,底层调用 Hashtable方法 put
String getProperty(String key) 使用此属性列表中指定的键搜索属性
Set<String> stringPropertyNames()从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
Properties和IO流结合的方法:
void load(InputStream inStream) 从输入字节流读取属性列表(键和元素对)
void load(Reader reader) 从输入字符流读取属性列表(键和元素对)
void store(OutputStream out, Stringcomments)将此属性列表(键和元素对)写入此 Properties表中,以适合于使用 load(InputStream)方法的格式写入输出字节流
void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流