什么是流?
内存与存储设备之间传输数据的通道。
流的分类:
按数据传输的方向来分(以内存为参照):
1. 输入流:硬盘 ---> 内存
2. 输出流:内存 ---> 硬盘
按单位来分:
1.字节流:以字节为单位,啥数据都可以传
2.字符流:以字符为单位,只能传文本数据
按功能来分:
1.节点流:单纯地传数据
2.过滤流:在节点流的基础上,添加一些扩展功能
字节流:
字节流的父类(抽象类):
1.InputStream:字节输入流
2.OutputStream:字节输出流
InputStream的方法 | 作用 | 返回值 |
available() | 返回可以读取的字节数 | int |
close() | 关闭流 | void |
read() | 从输入流中读取下一个字节 | int |
read(byte[] b) | 从输入流中读部分字节,读到byte[]数组中 | int |
read(byte[] b, int off, int len) | 从off下标开始,将输入流中最多len个字节的数据,读到byte[]数组中 | int |
skip(long n) | 跳过n个字节 | long |
OutputStream的方法 | 作用 | 返回值 |
close() | 关闭流 | void |
flush() | 刷新流,并强制写出缓存中的所有字节 | void |
write(byte[] b) | 把byte[]数组中的数据,写到流中 | void |
write(byte[] b, int off, int len) | 从off下标开始,将byte[]数组中的len个字节写到流中 | void |
write(int b) | 将指定字节写到流中 | void |
FileInputStream(InputStream的子类):
构造方法:
FileInputStream(String name):连接name路径下的文件
创建文件D:\test.txt
返回结果:
换种方法,把数据读到byte[]数组中:
输出结果:
改进:
输出结果:
FileOutputStream(OutputStream的子类):
运行后自动创建了D:\here.txt文件:
一次性写入一个字符串:
用上面的方法写入数据,会默认覆盖原有的数据,解决方法:
执行结果:
案例:字节流复制文件
方法:把硬盘上的文件a读到内存,再从内存中读到文件b中。
字节缓冲流:增强字节流的功能
自带一个缓冲区,读的时候就不用从硬盘里面读,可以直接从缓冲区里面读。作用相当于之前的byte[]数组。
1.BufferedInputStream
2.BufferedOutputStream
对象流:增强缓冲区的功能,也增强了读写对象的功能
ObjectOutputStream
方法 | 作用 | 返回值 |
readObject() | 从ObjectInputStream中读取对象 | Object |
ObjectInputStream:
方法 | 作用 | 返回值 |
writeObject(Object) | 将指定的对象写入ObjectOutputStream | void |
序列化和反序列化:使用流传输对象
先写一个Student的类:
注意:要序列化Student类,那么它必须要实例化Serializable接口。
把它序列化到硬盘:
把硬盘里的反序列化到内存:
注意:序列化中的对象属性也要求实现Serializable接口。
也就是说,如果Student里面还有一个private Address address。那么这个Address类也要实现Serializable接口。
关于序列化版本号:
如果不希望某个属性被序列化,可以使用transient(短暂的)修饰。
比如:private transient int age; 那么这个age就不能被序列化。
Student s = new Student("张三", 20);在序列化反序列化之后,name=张三,age=0.
注意:静态的属性,也不能被序列化。
也可以一次性序列化多个对象。放在集合里面就可以,然后序列化集合对象。
字符编码(当编码的方式和解码的方式不一致,就会出现乱码):
字符编码 | 作用 |
ISO-8859-1 | 收录除了ASCII码之外的文字符号。采用一个字节来表示,也就是说,最多能表示256个字符。 |
UTF-8 | 全世界通用,采用1个或2个或3个字节来表示。 |
GB2312 | 简体中文,95年之前用的。采用1个或2个字节表示。 |
GBK | 95年之后,对GB2312做了一个升级,成了GBK。采用1个或2个字节表示。 |
BIG5 | 台湾,繁体中文。 |
创建一个D:\hello.txt:
通过文件另存为查看文件编码未UTF-8。因为在UTF-8中一个汉字占3个字节。用FileInputStream只能一个字节一个字节地读,用(char)data 只能把一个字节转换成char。所以会出现问题。
所以需要用到字符流。
字符流的父类(抽象类):
Reader:字符输入流
方法 | 作用 | 返回值 |
close() | 关闭流 | void |
read() | 读取单个字符 | int |
read(char[] cbuf) | 把字符读到数组里面 | int |
read(CharBuffer target) | 将字符读到缓冲区 | int |
skip(long n) | 跳过字符 | long |
Writer:字符输出流
方法 | 作用 | 返回值 |
append(char c) | 追加字符 | writer |
close() | 关闭流 | void |
flush() | 刷新 | void |
write(char[] buff) | 写入字符数组 | void |
write(int c) | 写入单个字符 | void |
write(String str) | 写入字符串 | void |
子类:
FileReader:public int read(char[] c) 从流中读取多个字符,将读到的内容存入c数组,返回实际读到的字符数。如果达到文件的尾部,则返回-1
FileWriter:public void write(String str) 一次写多个字符,将b数组中所有的字符,写入输出流
案例:使用FileReader和FileWriter复制文件(只能复制文本文件,不能复制图片、视频等二进制文件)
字符缓冲流:
BufferedReader
方法 | 作用 | 返回值 |
close() | 关闭流 | void |
read() | 读取单个字符 | int |
read(char[] cbuf, int off, int len) | 将字符读入数组的某一部分 | int |
readLine() | 读取一个文本行 | String |
skip(long n) | 跳过字符 | long |
方法一: 以char[]数组的方式读
方法二:一行一行地读
BufferedWriter
方法 | 作用 | 返回值 |
close() | 关闭流 | void |
flush() | 刷新 | void |
newLine() | 写入一个行分隔符 | void |
write(char[] cbuf, int off, int len) | 写入字符数组的一部分 | void |
write(int c) | 写入单个字符 | void |
打印流:PrintWriter
封装了print()/println()方法,支持写入后换行
方法 | 作用 | 返回值 |
append(CharSequence csq, int start, int end) | 将指定字符序列的子序列添加到writer | PrintWriter |
close() | 关闭 | void |
flush() | 刷新 | void |
print(Object o) | 打印Object | void |
println() | 打印换行 | void |
write(String s, int off, int len) | 写入字符串的一部分 | void |
转换流(桥转换流):字节流 -->字符流,并且可以设置编码
InputStreamReader
方法 | 作用 | 返回值 |
getEncoding() | 查看字符编码 | String |
read(char[] cbuff, int offset, int length) | 将字符读入数组中的某一部分 | int |
OutputStreamWriter
方法 | 作用 | 返回值 |
getEncoding() | 查看字符编码 | String |
write(String str, int off, int len) | 写入字符串的某一部分 | void |
File类:代表物理盘符中的一个文件或者文件夹
方法 | 作用 |
createNewFile() | 创建一个新文件 |
mkdir() | 创建一个新目录 |
delete() | 删除文件或者空目录 |
exists() | 判断对象是否存在 |
getAbsolutePath() | 获取文件的绝对路径 |
getName() | 获取名字 |
getParent() | 获取所在的目录 |
isDirectory() | 判断是不是目录 |
isFile() | 判断是不是文件 |
length() | 获取文件的长度 |
listFiles() | 列出目录中所有的内容 |
renameTo() | 重命名 |
分隔符:
对文件的操作:
对文件夹的操作:
文件过滤器:FileFilter接口
递归遍历目录:
递归删除目录:
Propertise属性集合:
特点:
1.属性名和属性值都是字符串类型
2.没有泛型(因为类型已经确定了,都是字符串)
3.和流有关
方法 | 作用 | 返回值 |
getProperties(String key) | 通过key获取value | String |
list(PrintStream out) | 将properties输出到指定的输出流 | void |
load(InputStream inStream) | 从输入流中读到properties中 | void |
store(OutputStream out, String comments) | 保存 | void |
stringPropertyName() | 返回properties中所有的key的集合 | Set<String> |