# API-输入/输出类库 (Package java.io)

# 6.1 File

# 6.1.1 基本信息

Package java.io
public class File

  • 表示文件或者目录的类。
  • 构造函数File(String pathname)可以用来构造一个文件。
    • 目标文件不存在时不会创建
    • 创建File对象时,不会在计算机中检查是否存在。只是将传入的路径标识为File对象。

    注意

    • Windows 下,使用\\分割目录;而 Linux 以/分割
      使用File.separator()来获取目录分隔符

    • Windows 下,使用;分割不同的路径;而 Linux 以:分割
      使用File.pathSeparator()来获取路径分隔符

# 6.1.2 重要方法

  • createNewFile()
    创建文件。当文件不存在时,会创建新文件。
    要求文件存放路径真实存在。只能用于创建文件,但不能创建目录。

  • mkdir()
    只能用于创建目录。
    只能创建一层目录。

  • mkdirs()
    创建多层目录。

  • delete()
    删除文件/目录。从计算机中真正移除。
    若删除目录为目录,且该目录下有子目录或者文件时,则无法删除。

  • listFiles()
    获取文件、获取目录的子文件、子目录。
    以文件类对象数组形式返回。

  • isDirectory()
    判断是否为目录。

  • isFile()
    判断是否为文件。

  • getName()
    获取文件名。

  • canWrite()
    判断文件是否可写。

# 6.1.3 路径

  • 绝对路径

    • 以盘符或者/开头的路径
    • 使用getAbsolutePath()获取
  • 相对路径

    • 不以盘符或者/开头的路径
    • ..表示上一层目录
    • 使用getPath()获取

路径相关的其他重要方法

  • getParent()
    获取父目录。

  • lastModified()
    获取最后修改时间,返回值为自 1970/01/01 00:00:00 至最后修改时间的毫秒值。

  • setReadOnly()
    设置文件只读。

  • renameTo()
    重命名文件。
    若文件路径没有发生改变,则重命名;若改变则执行剪切。

# 6.2 I/O Stream

java.io是一套用于传输数据的 API。根据数据传输方向、数据传输形式可以分为四类,以及他们的关系:

  • 根据数据传输方向:输入流、输出流
    输入流:当数据从外部流向程序。例如:读取文件,将数据文件读取到程序中。
    输出流:数据从程序流向外部。例如:向文件写数据,数据从程序流向文件。
  • 根据数据的传输形式:字节流、字符流
输入流 输出流
字节流 InputStream OutputStream
字符流 Reader Writer

*这四个基本流都是抽象类。

  • 数据的一般来源和目的地有:硬盘、网络、输入设备和内存

# 6.2.1 缓冲流

  • BufferedReader
    需要字符输入流作为参数,缓冲流仅提供缓冲区

  • BufferedWriter
    使用newLine()写入换行符

# 6.2.2 字节流

以字节形式读取数据,没有缓冲区。

# 6.2.3 转换流

表层以字符形式,底层以字节形式。

  • InputStreamReader
    转换输入流,将字节流转换为字符流

  • OutputStreamWriter
    转换输出流,将字节流转化为字符流
    例如:将数据写出 txt 文件:使用输出流,字符流,且和文件有关。故使用FileWrite(它是OutputStreamWriter的子类)

    关于 FileWriter

    • 使用构造函数FileWriter(String path)来创建新文件。
    • 写出数据时并不直接写到文件中,而是写入缓冲区。
      缓冲区未满但代码已经运行结束 → flush()冲出。
    • 使用close()关闭流对象。
      缓冲区未冲刷关闭流对象前,自动执行flush()
      关闭流对象后,对象没有被释放 → 赋值为null,标识为可回收

# 6.2.4 系统(标准)流

  • System.in 标准输入流
  • System.out 标准输出流
  • System.err 标准错误流

# 6.2.5 打印流

  • PrintWriter
    字符流

  • PrintStream
    字节流

# 6.2.6 合并流

SequenceInputStream

  • 字节流,可以合并多个字节输入流
  • 将多个字节输入流进行合并时,需要将其放到Vector集合,利用Vector集合产生一个Enumeration对象
  • 利用Enumeration对象构造合并流对象
  • 只有输入流,没有输出流

# 6.2.7 序列化/反序列化

  • 序列化:将对象完成存储(持久化)。ObjectOutputStream
  • 反序列化:将序列化的对象还原。ObjectInputStream

注意

  • 实现对象序列化,需实现Serializable接口
    接口中没有任何方法和属性,仅用来标识类产生的对象可以被序列化
  • static/transient修饰的属性不会被序列化
  • 每个类在序列化时都有版本号
    • 没有手动指定,JVM 在编译时会自动计算版本号
    • 手动指定则不再自动计算
    • 对象在反序列化时会比较当前类中版本号和对象版本号是否一致
  • 集合和数组不能被序列化

特别的

Java 的序列化不是常用序列化手段,它存在以下问题:序列化产生的数据量大、速度慢、不能跨语言。

# 6.2.8 AutoCloseable

  • 当流实现了这个接口可以被自动关闭。
  • 需要写在try(// Codes goes here…)
  • 当执行完毕会自动调用close()

# 6.2.9 异常处理

  • 将流对象放在try外定义并赋值null, 在try中初始化
  • 在关闭之前判断对象是否初始化成功
  • 将流强制置空,防止关流失败无法释放文件 在写完数据后手动添加flush,防止关流失败数据丢失