一、流的定义(流的目的:永久性的保存数据对象)
流就是I/O流,I就是input,O就是output。流其实是一个相对抽象的概念,就好像是一个传输数据的通道。Java中对文件的操作就是以流的方式进行的,流是一组字节的集合,表示有连接源和目的地的有方向的数据通道。
Java将数据从源(文件、内存、键盘、网络)读到了内存中,形成了流,然后将这些流还可以写到另外的目的地(文件、内存、控制台、网络),之所以称之为流,是因为这个数据序列在不同时刻所操作的是源的不同部分。
二、流的分类
1、按照流的传输方向
输入流:读取数据,从数据源到当前程序(数据源:磁盘、鼠标、键盘、网络......)--->基类:InputStream、Reader
输出流:写数据,从当前程序到目的源(目的源:磁盘、网络通信、显示器......)--->基类:OutputStream、Writer
2、按照流的处理单元
字节流:机器可以识别的,二进制文件流--->基类:InputStream、OutputStream
字符流:人可识别的字符--->Reader、Writer
3、按照流的角色
节点流:直接和数据源相连接
处理流:一个已存在的流进行连接和封装,通过封装后的流来实现数据的读、写功能
三、详细介绍各类
1、File类是IO包中唯一代表磁盘文件本身的对象,通过File来创建、删除、重命名文件,File类对象的主要作用就是用来获取文本本身的一些信息。
File(String pathname):根据一个路径得到一个File对象
A:构造方法: File(String parent,String Child):根据一个目录和一个子文件/目录得到File对象
File(File parent,String Child):根据一个父File对象和一个子文件/目录得到File对象
2、输入流
3、输出流
4、随机访问 RandomAccessFile
RandomAccessFile是用来支持读写随机存取文件的类。随机存取文件的行为就像存取在文件系统里一个很大的字节数组一样。该对象只能操作文件,所以构造函数接收两种类型的参数:a.字符串文件路径;b.File对象。该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r,rw)注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;
如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。可以用于多线程下载或多个线程同时写数据到文件。
特有方法:getFilePointer():返回文件记录指针的当前位置
seek(long pos):将文件记录指针定位到pos的位置
四、代码演示
步骤1:打开读/写字符/字节流
步骤2:读/写操作
步骤3:关闭流
try {
//创建写字符流 会有异常考虑
FileWriter fileWriter=new FileWriter(path);
//每次写入一个字符
fileWriter.write(97);
//通过char数组,写入数据
char[] chars=new char[]{'a','b','c'};
fileWriter.write(chars);
//通过char数组写入数据,第一个参数:需要写入读取的数据源,
//第二个参数:在数据源中读取数据的起始位置,第三个参数:从起始位置读取数据的长度
fileWriter.write(chars,0,3);
//写入字符串
fileWriter.write("hello");
//写入字符串:从指定位置写入指定长度数据
fileWriter.write("hello1",0,5);
//写字符流关闭
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
五、总结(直接Copy老师的结论了)
操作流需要明确4个问题
问题1:操作时进行读还是写(数据源到当前程序、当前程序到数据目的)
源:读数据 inputStream \reader
目的:写数据 outputStream\ writer
问题2:明确操作的是字节还是字符
源:
字节:InputStream
字符:Reader
目的:
字节:OutputStream
字符:Writer
(明确操作那个基类的流)
问题3:数据做在的具体设备
源:
磁盘数据:File
内存数据:char、array
键盘:System.in
网络:socket
目的:
磁盘数据:File
内存数据:char、array
屏幕:System.out
网络:socket
(明确具体实现类)
问题4:是否需要额外功能
考虑效率: BufferXXX
流转换:inputStreamReader\outputStreamWriter