基本分类
-
所有的流都从4个流(抽象类)派生:
- 字节流InputStream、OutputStream,二进制的输入输出
- 字符流reader、writer,字符的输入输出
-
节点流
- 低级流,直接与数据源连接,如字节流、字符流
-
处理流、包装流
- 高级流,必须建立在低级流上,对低级流进一步处理
- 好处是更改节点流就可改变数据源,方便修改代码
- 功能:增加缓冲,增强性能(例如BufferReader)、一次性输出/输入大量内容(例如DataInputStream)
File类
关于路径名:win下应该使用反斜杠\,但java中\是转义字符,所以要用两条反斜杠\,推荐使用斜杠/,java将其认为与平台无关的分隔符。
File类各种方法
-
举例路径:E:\计算机科学\书\挡板门专利.pdf
- getName: 挡板门专利.pdf
- getAbsolutePath: E:\计算机科学\书\挡板门专利.pdf
- getAbsoluteFile(返回File对象): E:\计算机科学\书\挡板门专利.pdf
- getParent(): E:\计算机科学\书
- isFile: true
- isDirectory: false
- list()返回目录下的文件名String[]
- listFiles()返回目录下文件的File[]
简单实例(文件复制):
File f = new File("E:/计算机科学/书/test.txt");
File f2 = new File("E:/计算机科学/书/test2.txt");
FileReader fr = new FileReader(f);
FileWriter fw = new FileWriter(f2);
//字符流reader使用char数组
char[] chars = new char[3];
int hasNext = 0;
//read方法根据chars的length读取数据到chars,并返回int数据长度,没有数据则返回-1
while ((hasNext = fr.read(chars)) > 0) {
//根据返回的长度hasNext写入fw的文件f2
fw.write(chars, 0, hasNext); }
//由于FileReader/FileWriter不属于内存中的资源,因此JVM不会回收它
fr.close();
fw.close();
说明:
- 所有IO类都实现了AutoClosable接口,因此可以使用带资源的try语句实现自动关闭
其他包装流:
- BufferedReader有一个readLine方法,可以读取一行文字,常用来读取文本文件
- BufferedReader可以一次读取一定量的数据到缓存中,然后再处理,减少了磁盘读取次数
对象序列化
- 实现序列化的对象可以转换为字节流,存储在硬盘上或者通过网络传输
- 反序列化就是将字节流恢复成对象
- 实现序列化的类必须实现Serializable接口,该接口是个标记性接口,不需要实现方法
- 通常建议,每个JavaBean都实现序列化
- 反序列化时必须提供对象对应的class文件,否则就会引起ClassNotFoundException
- 反序列化并没有调用构造器,而是直接根据字节流创造了对象
File f = new File("E:/计算机科学/书/object.txt");
try (FileOutputStream fos = new FileOutputStream(f);
ObjectOutputStream oos = new ObjectOutputStream(fos);
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis)) {
String str = new String("huangxiaoming");
//使用writeObject方法直接写入
oos.writeObject(str);
//使用readObject方法读取,返回的是Object类型
System.out.println(ois.readObject());
} catch (IOException e) {
e.printStackTrace();
//反序列化时必须提供对象对应的class文件,否则就会引起ClassNotFoundException
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
- 序列化的类的成员变量如果是引用变量,则该变量的类也必须实现序列化接口
- 序列化时,会把成员变量也一起序列化
- 如果两个对象的变量引用了同一个对象,则只会序列化一次并编号,第二次会根据编号直接输出对象,因此,一个对象只能序列化一次,如果序列化后对象改变了成员变量,再序列化后,输出的仍是第一次序列化的对象
- transient关键字,用于修饰实例变量,表示该变量不参与序列化
- 常见的private static final long serialVersionUID,用于标识class的版本,反序列时使用的class版本必须与序列化时一致(class文件可以改变,版本必须相同)