11.1 文件
11.1.1 文件流
- 流:数据在数据源(文件)和程序(内存)之间经历的路径
- 输入流:数据从数据源(文件)到程序(内存)的路径
- 输出流:数据从程序(内存)到数据源(文件)的路径
11.1.2 常用操作
- 创建文件对象
new File(String str)
:通过指定路径创建File实例File(File parent, String child)
:通过父目录文件和子路径搭配创建File实例File(String parent, String child)
:通过父目录和子路径搭配创建File实例
- 获取文件相关信息
createNewFile()
:在指定路径生成目标文件,并保存在磁盘里
- 该方法有异常问题
getName()
:获取文件名getAbsolutePath()
:获取文件的绝对路径(带文件名)getParent()
:获取父级目录length()
获取文件内容有多少字节,根据文件的编码获取
- UTF-8编码中,汉字3个字节
exists()
:文件是否存在isFile()
:是不是一个文件isDirectory()
:是不是一个目录
- 目录操作和文件删除:
delete()
:删除文件或空文件夹mkdir()
:创建一级目录mkdirs()
:创建多级目录
11.2 IO流原理及分类
11.2.1 I/O流原理
- 用于数据传输,如读写文件,网络通讯。
- java.io包下提供了各种流(stream)类和接口,用以获取不同类的数据,并通过方法输入或输出数据。
- 输入input:读取外部数据到内存(程序)中
- 输出output:将程序(内存)中的数据输出到存储设备中。
11.2.2 流的分类:写、out:自身→外部,读、input:外部→自身
- 按照操作数据单位分:字节流(8字节)二进制文件、字符流(按字符)文本文件
- 按数据流向:输入流、输出流
- 按流的角色:节点流、处理流/包装流
- 节点流:从一个特定的数据源读写数据
- 数据源:存放数据的地方,可以是文件、字符串、数组、管道
- 处理流/包装流:建立在已有的流之上,为程序提供更强大、更灵活的读写功能
- 如BufferedReader、BufferedWriter
- 处理流类的底层封装了节点流的Wrtie或Reader对象,根据多态,可以使用各种Writer和Reader的子类对象
节点流和处理流的区别和联系:
- 节点流是底层流,直接更数据源相接
- 处理流包装节点流,可以消除不同节点流的实现差异,也可以提供更方便的方法完成输入输出
- 处理流对节点流的包装,使用了修饰器涉及模式,不会直接与数据源相连
- 处理流提高了性能:主要以增加缓冲的方式提高输入输出的效率
- 处理流提供了操作的便捷:处理流可能提供了一系列编辑的方法来一次输入输出大批量的数据,使用更加灵活方便。
抽象基类 |
字节流 |
字符流 |
输入流 |
InputStream |
Reader |
输出流 |
OutputStream |
Writer |
- java的io流涉及40多个类,都是从上述4个抽象基类派生而来
- 这4个基类派生出来的子类名称都是以基类名作为子类名的后缀
- IO流体系图
11.3 节点流/文件流
11.3.1 FileInputStream
- 创建文件输入流对象:
new FileInputStream(filePath)
:
- 有异常问题
read()
:从输入流中读取一个字节的数据,
- 到达文件末尾时,返回-1(读取完毕)
- 有异常问题
- 读入的字节数据是ASCII编码,使用字符强转可得到原文
read(byte[] b)
:一次读取b.length()个字节存入到b中,返回实际读取的字节数量
- 到达文件末尾时,返回-1(读取完毕)
- 有异常问题
- 读入的字节数据是ASCII编码组成的数组,转换为字符串时可使用
String(byte[] bytes, int offset, int length)
构造器
- offset:byte[]数组起点下标
- length:读入byte[]字节长度
read(byte[] b, int off, int len)
:开发中使用这个
- 到达文件末尾时,返回-1(读取完毕)
- 有异常问题
close()
:关闭文件输入流,并释放与该流相关的所有系统资源
- 由于创建输入流对象有异常问题,该方法须在finally块中调用,以保证确实执行。
11.3.2 FileOutputStream
- 创建文件输出流对象:
new FileOutputStream(filePath)
:覆盖模式new FileOutputStream(filePath, true)
:追加模式:第二个参数设置为true时,输出的字节流是追加的方式- 有异常问题
write(int b)
:将单个字节数据输出到输出流,传入的是一个ASCII整数,或者一个字符(会自动类型转换为整型)
- 有异常问题
write(byte[] b)
:将b.length()个字节输出到输出流
- 有异常问题
- 可搭配String的
getBytes(str)
使用,将字符串转换为字符数组
write(byte[] b, int off, int len)
:将字节数组b,从下标off开始的len个字节数据输出到输出流。开发中使用这个
- 有异常问题
close()
:关闭文件输出流,并释放与该流相关的所有系统资源
- 由于创建输出流对象有异常问题,该方法须在finally块中调用,以保证确实执行。
11.3.3 文件拷贝
- 搭配输入输出流使用
11.3.4 FileReader
- 创建文件读取对象:
new FileReader(filePath)
:
- 有异常问题
reader()
:读取单个字符,读入的是个整数
- 到达文件末尾时,返回-1(读取完毕)
- 有异常问题
- 读入的字符数据是ASCII编码,使用字符强转可得到原文
read(byte[] b)
:一次读取b.length()个字符存入到b中,返回实际读取的字符数量
- 到达文件末尾时,返回-1(读取完毕)
- 有异常问题
- 读入的字符数据是ASCII编码组成的数组,转换为字符串时可使用
String(char[] chars, int offset, int length)
构造器
- offset:char[]数组起点下标
- length:读入char[]字节长度
read(char[] b, int off, int len)
:开发中使用这个
- 到达文件末尾时,返回-1(读取完毕)
- 有异常问题
close()
:关闭文件读取对象,并释放与该流相关的所有系统资源
- 由于创建文件读取对象有异常问题,该方法须在finally块中调用,以保证确实执行。
11.3.5 FileWrite
- 创建文件写入流对象:
new FileWriter(filePath)
:覆盖模式new FileWriter(filePath, true)
:追加模式:第二个参数设置为true- 有异常问题
write(int b)
:将单个字符数据输出到输出流,传入的是一个ASCII整数,或者一个字符(会自动类型转换为整型)
- 有异常问题
write(char[] b)
:将b.length()个字符输出到输出流
- 有异常问题
write(char[] b, int off, int len)
:将字符数组b,从下标off开始的len个字符数据输出到输出流。开发中使用这个
- 有异常问题
write(String str)
:写入整个字符串write(String str, int off, int len)
:写入字符串指定部分close()
:关闭文件输出流,并释放与该流相关的所有系统资源
- 由于创建输出流对象有异常问题,该方法须在finally块中调用,以保证确实执行。
- FileWtrie必须关闭流(close())或(flush(),否则不能真正保存到文件
- 等价于flush()和关闭
11.4 处理流
- BufferedReader和BufferedWriter
- 属于字符流,一般用于处理文本文件,处理声音、视频、doc、pdf等二进制文件时有数据丢失的风险。
- 关闭流时,只需要关闭外层的BufferedReader或BufferedWriter即可,而不是传入的Reader、Writer对象,底层会自动关闭对应的传入Reader、Writer对象
- BufferedInputStream和BufferedOutputStream
- 属于字节流,既可处理文本文件,也可处理二进制文件
11.4.1 BufferedReader
- 创建对象:
new BufferedReader(Reader in)
:
- 有异常问题。
- 异常存在于传入的Reader in对象
readLine()
:按行读取,读取完毕返回null
- 不读入换行
11.5.2 BufferedWriter
- 创建对象:
new BufferedWriter(Writer out)
- 有异常问题。
- 异常存在于传入的Writer out对象
write(String s, int off, int len)
:写入字符串的一部分
- 好像不要off和len的时候是传入整个字符串?
newLine()
:插入一个和系统相关的换行符
11.4.3 BufferedInputStream
new BufferedInputStream(InputStream in)
- 类似BufferedReader
- 使用的方法是:
read(byte[] b, int off, int len)
11.4.4 BufferedOutputStream
new BufferedOutputStream(OutputStream out)
- 类似于BufferedWriter
- 使用的方法是:
write(byte[] b, int off, int len)
11.4.5 序列化和反序列化
- 序列化:保存值和数据类型到文件
- 反序列化:将保存到文件的数据值和数据类型进行恢复
- 对象要可序列化,则要求该对象实现
Serializable
或Externalizable
接口。
- 一般使用
Serializable
,该接口为标记接口——没有任何属性和方法 Externalizable
,继承自Serializable
,需要重写两个方法
- 注意事项
- 读写顺序要一致
- 序列化或反序列化的对象必须实现
Serializable
或Externalizable
接口。 - 序列化的对象建议添加
private static final long serialVersionUID
,提高兼容性 - 序列化的对象,会默认初始化除static和transient修饰的成员
- 序列化的对象,其属性类型也需要实现序列化接口,有异常问题
- 序列化具有继承性,其子类自动可序列化
11.4.6 ObjectOutputStream
- 特征:字节流、处理流、对象流、提供序列化功能
- 创建对象:
new ObjectOutputStream(OutputStream out)
writeInt(int)
:自动装箱,写一个32位的整形数writeBoolean(boolean)
:自动装箱writeChar(int)
:自动装箱,写一个16位字符,可传入字符,会自动转换为intwriteDouble(double)
:自动装箱,写一个64位双精度浮点数writeUTF(String)
:以UTF-8模式写入字符串writeObject(Object)
:将指定对象写入close()
- 上述均有异常问题。
11.4.7 ObjectInputStream
- 特征:字节流、处理流、对象流、提供反序列化功能,反序列化顺序必须与序列化顺序一致。
- 创建对象:
new ObjectInputStream(InputStream input)
readInt()
readBoolean()
readChar()
readDouble()
readUTF()
readObject()
:底层表现多塔的特征,编译类型是Object,运行类型是实际的类型,底层会进行造型和强转。但如果使用运行类型的方法,需要进行显式强转。close()
- 上述均有异常问题
11.5 标准输入流和输出流(java.lang.Object)
System.in
类:编译类型为InputStream
、运行类型为BufferedInputStream
- 标准输入
- 输入源键盘
- 返回
InputStream
System.out
类:编译类型为PrintStream
、运行类型为PrintStream
- 标准输出
- 输出源显示器
- 返回
OutputStream
11.6 转换流
InputStreamReader
(字符流):
- 默认情况下,读取文件时按照utf-8的形式,
Reader
的子类- 可以将
InputStream
(字节流)包装成/转换成Reader
(字符流) InputStreamReader(InputStream in, Charset cs)
:按照读取文件的cs编码格式进行读入
OutputStreamWriter
(字符流):
- 指定处理编码
Writer
的子类- 可以将
OutputStream
(字节流)转换成Writer
(字符流) OutputStreamReader(OutputStream in, Charset cs)
- 主要用于解决中文文本数据
- 中文文本数据有乱码问题
- 中文文本按照字符流处理(读取和写入)效率更高
11.7 打印流
- 只有输出流没有输入流
11.7.1 PrintStream
- 构造器(常用):
PrintStream(OutputStream out)
:
PrintStream(System.out)
:默认屏幕输出
PrintStream(File file)
:可指定编码PrintStream(String fileName)
:可指定编码PrintStream(Writer out)
:可指定编码
- 使用:
PrintStream out = System.out
out.print()
:默认情况下,输出位置是标准输出——显示器print()
底层使用的是write()
,故可以使用字节流的write()
方法进行时输出- 修改输出位置:
System.setOut(PrintStream ps)
,然后调用out.print()
- 根据创建的
ps
对象,可以输出到指定文件
- 需要关闭。
11.7.2 PrintWriter
- 构造器:
PrintWriter(OutputStream out)
:
PrintWriter(System.out)
:默认屏幕输出
PrintWriter(File file)
:可指定编码PrintWriter(String fileName)
:可指定编码PrintWriter(Writer out)
:可指定编码
- 使用:
- 调用
print()
方法
- 需要关闭。
11.8 Properties
- 作用:专门用于读写配置文件的集合类
- 配置文件格式:
键=值
- 键值对不需要有空格
- 值不需要使用引号
- 默认类型为String
- 创建对象:
new Properties()
- 常见方法:
load(Reader reader)
loaad(InputStream instream)
:加载配置文件list(PrintWriter out)
:将此属性列表打印到指定的输出流(键值对的形式)
list(System.out)
:屏幕输出
list(PrintStream out)
getProperty(String key)
:根据key获取valuesetProperty(String key, String value)
:修改、添加键值对到Properties类的对象(此时还没添加到文件里)store(OutputStream out, String comments)
:将k-v存储到文件中
- comments会添加文件的开头,以#注释,一般可置为null
store(Writer writer, String comments)
- IDEA中使用路径:
- 绝对路径
- 工程路径:
src/io.properties
- 模块路径:
模块名/src/io.properties