Java.io包中操作文件内容的主要有两大类:字节流、字符流
输出流:对象到目的地文件(写进文件)
输入流:已有文件到目的地对象(输进对象)
一、字节流和字符流综述:
1. stream结尾都是字节流,reader和writer结尾都是字符流。
2. 字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串
3. InputStream,OutputStream主要处理二进制文件和字节流,Reader,Writer处理字符流(四个都是抽象类)
4. 字符流操作才能使用缓冲区
Java中输入输出包含文本I/O和二进制I/O(下面对文本I/O只做简要笔记,二进制I/O中重要之处有注明以及代码)
二、文本I/O与二进制I/O综述:
1. 文本I/O涉及编码和解码(机器自动进行的),而二进制I/O不涉及,所以二进制I/O更加高效
2. windows的记事本以及Unix下的编辑器为文本文件,其他都为二进制文件
3. 从计算机的角度来说,所有文件都是二进制文件
4. 二进制文件与机器的编码方式无关所以它是可移植的
5. 文本I/O在文件中以编码的形式保存,而二进制I/O在文件中以相同的字节保存
三、文本I/O
1. File类:在程序中,如果使用绝对文件名,可能会降低程序的可移植性(比如Java和UNIX一样,以“/”作为目录分隔符,而在Windows系统中用的是”\”作为目录分隔符)
2. 输入流Writer
3. 输出流Rider
四、二进制I/O
1.输出流:InputStream
2. 输入流:OutputStream
注:以上两个是是二进制I/O类的根类
3. FileInputStream、FIleOutputStream、BufferedInputStream、BufferedOutputStream都没有引入新方法
4. 实例1——使用字节流复制文件:
import java.io.*;
public class ImageCopy {
public static void main(String[] args) {
//使用try-with-sourse语句块(资源中的子类型必须具备close()方法),可以自动关闭
try (FileInputStream fis=new FileInputStream(“2.jpg”);
FileOutputStream fos=new FileOutputStream(“d:/JavaStudy/copy.jpg”)){
int flag=0;
while((flag=fis.read())!=-1){
fos.write(flag);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
注:
如多是手动调用close方法,需要遵循先“打开的后释放”的原则
字符类型的,如txt文件,用字符流写入写出
5. DataInput(Output)Stream实现字节与基本类型或字符串之间的转换
6. 用EOFException也可判断文件是否到达末尾
catch (EOFException e) {
System.out.println(“文件已到末尾”);
}
7. BufferedInputStream:使用时,磁盘上的整块数据会一次性的读入到内存中的缓冲区,然后从缓冲区中将个别的数据传到程序中;
BufferedOutputStream:使用时,个别的数据首先写入到内存中的缓冲区中,缓存区满后,缓冲区中的数据会一次性的写入到磁盘中
8. 如果没有指定缓存区的大小,默认为512个字节
9. 应该总是使用缓冲区I/O来加速文件的输入/输出(在大文件中,会看到实质性的性能提升)
DataOutputStream output=new DataOutputStream(new BufferedOutputStream(new FileOutputStream(“temp.dat”)));
10.实例2—命令行传参的文件复制
所用命令如下:java Copy sourse target
- 对象I/O:ObjectInputStream和ObjectOutputStream类可用于读/写可序列化的对象
注:静态变量没有序列化 - 完全可以用ObjectInputStream和ObjectOutputStream类代替DataOutputStream和DataIntputStream类
- ObjectInputStream和ObjectOutputStream类可以实现对象的输入和输出,从ObjectInputStream读取对象时,必须与其写入时的类型和顺序相同,所以为了得到需要的类型,必须使用Java安全的类型转换
- Serializable接口
并不是每一个对象都可以写入到输出流,只有可序列化(serializable)的能够写入,Serializable接口是一个标记接口,没有方法 - Java提供一个内在机制自动完成写对象的过程,这个过程称为对象序列化,在ObjectOutputStream中实现;读取过程称为反序列化,在ObjectInputStream中实现
- 如果一个对象是Serializable的实例,但是包含非序列化的实例数据域,可用transient关键字修饰,JVM会忽略这些数据域
- 如果一次对象不止一次写入对象流,就只存储序列号。读出这些对象时,它们的引用相同
五、随机访问文件 - Java中RandomAccessFile类,允许文件从任意的位置进行数据读写
- 只读的或只写的都称为顺序流,顺序访问的文件不能更新
- 随机访问文件是由字节序列组成的,RandomAccessFile类可指定“r”和“rw”两种模式