Java语言第六篇流与File

流与File

    • Stream流
    • File类
    • IO流
      • 字节流
      • 字符流
      • 转换流
      • 对象操作流
      • Properties

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 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)方法的格式写入输出字符流

你可能感兴趣的:(编程语言,java,开发语言)