IO介绍&字节流
- IO流概述及分类
IO流简介
通过昨天的学习,大家都能够使用File类实现对文件和文件夹的一些操作了;但是还不能操作文件里面的数据;
要操作一个文件里面的数据,就要使用IO流来实现;
什么是IO流呢?
前面简单给大家说过IO的概念,IO就是input和output的缩写,表示数据相对于程序内存的输入和输出操作;
将数据输入内存,以及将数据输出内存,都需要专门的对象来操作;这些负责具体的输入或输出数据的对象,就是IO流对象;
在计算机领域,只要不在同一个程序的内存空间,数据的移动都需要通过IO流来实现;
- IO流分类
针对不同的输入和输出数据的需求,java提供了不同的IO流;为了更方便的学习掌握它们,可以根据不同的特点给它们进行分类:按照IO操作中数据的流向,可将IO流分为输入流和输出流(输入和输出,是相对于内存而言的):
输入流:将数据从程序之外的地方读进程序内存
输出流:将数据从程序内存输出到程序之外的地方;
按照IO操作中数据的类型,可将IO流分为字节流和字符流;
字节流:读写的数据都是字节数据;
字符流:读写的数据都是字符数据;
问题:什么是字节数据和字符数据?
字节数据:在计算机底层,所有数据都是使用二进制数字保存的;每八个二进制位,就是一个字节数据;
字符数据:一个文件使用记事本打开,如果里面的内容可以看懂,文件中的数据就是字符数据(word文档里面不是字符数据);
字符数据和字节数据的关系:字符底层也是使用字节数据保存的;根据不同的编码表的规则,一个字符可以由不同的字节数据表示;
问题:什么时候用字节流?什么时候用字符流?
所有文件都可以使用字节流;
如果一个文件里面是字符数据,应该使用字符流;
字节流和字符流也有输入和输出之分,可以再将它们进一步细分为四个类别:
字节输入流:
最高父类:InputStream;
子类:XxxInputStream;
字节输出流:
最高父类:OutputStream;
子类:XxxOutputStream;
字符输入流:
最高父类:Reader;
子类:XxxReader;
字符输出流:
最高父类:Writer;
子类:XxxWriter;
字节流
字节输入流
InputStream介绍
总结:
- InputStream在http://Java.io包中,使用需要手动导包;
- InputStream是我们Java中所有字节输入流的最高父类;
- InputStrean是一个抽象类,不能直接用它创建对象,而是应该使用它的儿子;
InputStream定义的读取数据的方法,必须掌握:
我们每次使用IO流之后,都需要调用这个函数进行关流,释放资源;
https://www.zhihu.com/video/1072881237848444928
FileInputStream介绍
说明:
使用FileInputstream类创建对象,必须指定要读取的那个文件;因为这个类就是专门用来从文件中读取数据的,所以必须告诉他要关联到哪一个文件上;
https://www.zhihu.com/video/1072881358300495872
使用FileInputStream读取文件数据
使用这个类读取文件中数据的步骤:
- 创建一个FileInputStream对象,关联到要读的文件;
- 调用这个对象的读取功能,读取数据,使用变量接受;
- 读完,关闭流,释放资源;
原始文件内容:
按字节读取:
按照字节数组读取数据:
一次读取指定个数的字节,放到指定数组中:
https://www.zhihu.com/video/1072881608251711488
FileInputStream使用注意事项
- 一个文件字节输入流读文件,读完就不能再读;
- 文件输入流不能关联到一个不存在的文件上;
- 文件输入流不能关联到一个文件夹上;
- 文件输入流不能关联到被系统使用的文件上;
总结:使用字节输入流读取文件中数据的步骤
https://www.zhihu.com/video/1072882136347897856
步骤:
- 创建一个文件字节输入流对象,关联到需要读取数据的文件上;
- 定义int变量或byte数组,用于接收读取到的字节数据;
- 循环读取数据,如果读取方法返回的结果是-1,就表示数据已经读取完毕;
- 关闭输入流对象
代码模板:
https://www.zhihu.com/video/1072882417643307008
字节输出流
OutputStream介绍
FileOutputStream介绍
总结:
- 这个类在http://java.io包中,使用需要手动导包;
- 这个类可以将字节数据写出到文件中;
- 这个类的对象关联的目标文件可以不存在,如果不存在,这个对象会自动创建(但是能否成功创建,由操作系统决定);
- 这个类只能写出字节数据;如果要写出字符数据,应该使用字符输出流;
使用FileOutputStream向文件写出数据
使用字节输出流向文件中写出数据的步骤:
- 创建FileOutputStream对象,关联到要写的文件;
- 调用函数向文件中写数据;
- 关闭流;
演示输出一个字节数据:
演示输出一个字节数组:
演示输出一个字节数组中的一部分:
https://www.zhihu.com/video/1073317466557583360
追加数据到文件结尾和输出换行
追加数据到文件结尾
向文件中输出换行
方法一:需要输出换行的地方输出换行符:n;
换行符n在windows操作系统里面没问题,但是不表示在其他操作系统中也可以正常工作;
最好的办法,直接获取操作系统中的换行符
方法二:使用System类中的方法,获取和平台有关的换行符;
输出换行,推荐使用这种方式;
https://www.zhihu.com/video/1073317654189625344
追加数据和换行练习
需求:书写一个日志工具类,可以将接受到的数据写入一个日志文件。
/**
需求:将一个磁盘中的一个文件复制到另一个磁盘中;
文件复制的原理:
https://www.zhihu.com/video/1073317930808344576
高效字节流:缓冲字节流
字节流的弊端:
字节流速度比较慢,因为每一次读写数据, 都要去操作硬盘上的文件;
字节流对数据的读写操作,都是实时和硬盘上的文件进行操作;
为了解决这个问题,提高IO读写数据的效率,java中提供了字节流缓冲区;
字节流缓冲区原理
结论:
缓冲区流能够提高效率的原因, 就是缓冲区流中有一个缓存空间,一般的io操作都是操作缓存空间的,减少了对硬盘的直接操作,所以能够提高效率;
缓冲字节流介绍
字节输入流缓冲区: BufferedInputStream;
缓冲区中默认缓冲数组的大小是8192字节;可以通过构造函数手动修改;
输入字节流缓冲区的作用主要是将数据读进缓存,读数据的方法InputStream一样;
字节输出流缓冲区:BufferedOutputStream;
https://www.zhihu.com/video/1073318064950640640
字节流缓冲区使用演示
用四种方式复制文件,对比效率
四种文件复制的方式:
普通字节流,每次读一个字节
普通字节流,每次读一个字节数组
缓冲字节流,每次读一个字节
缓冲字节流,每次读一个字节数组
代码:
public
结果:
结论:
按照效率从高到底排序:
字节流一次读写一个字节数组
字节流缓冲区一次读写一个字节数组;
字节流缓冲区一次读写一个字节数据;
字节流一次读写一个字节数据(开发中不要用这种)
实际开发中,一般使用字节流缓冲区或者字节流按照数组读写数据都可以,这二者速度相差不大;当读写数据的数组一样大时,字节流比缓冲区还稍微快一点;