Java基础(十七)——IO流
一、PrintStream——打印流
打印流:只有输出没有输入,直接打印数据。
1、print()和write()
打印流跟 write()都能写,有什么区别呢?看下面案例:
然后文件输出的并不是97,而是根据 ASCII 码表对应的字符:
所以,要输出数字 97,就用 PrintStream 里面的 print()方法:
结果:
注意:PrintStream 里面同样的有 write()方法,该效果也是输出 ASCII 码表对应的字符,print()方法才是输出数字。
2、System.out.println()
从学编程的第一天就开始接触的:System.out.println(),这就是在调用打印流。
看看System.out.println()调用了什么对象:
调用的是 PrintStream 对象。
PrintStream:打印字节流。上面的属于打印字节流。
PrintWriter:打印字符流 。下面的属于打印字符流
3、打印字符流(了解即可)
作用跟字符流一模一样。只不过要求用字节的时候用字节,要求用字符的时候就用字符。
4、输入重定向——改变目标源的来源
这个标题什么意思呢?先看以下代码:
就是平常的在控制台输入,然后控制台接收然后打印。输入固定在控制台那里。但是会存在一种情况,输入来源改变了,不从控制台接收:
可以看到,输入来源改变了,原本要从控制台输入也不再需要了,这个100来源于 io3.txt 文件里面的数字。不能一看到 Scanner 相关的就认为是从控制台输入,要注意输入来源。
5、输出重定向——改变输出目的源
输出两句到控制台:
这时候,将其中一句的输出改变,不再输出到控制台,控制输出到文件中:
可以发现,控制台只有一条语句,另外一条语句输出到文件中去。
二、内存流
内存流本质是字节流。
ByteArrayInputStream ——— 内存输入流
ByteArrayOutputStream —— 内存输出流
前面的都是程序跟文件互相写入读取。有一个流,是让程序跟内存相互写入读取:
1、内存输出流——ByteArrayOutputStream
把内存中的数据写入到文件中去:
2、内存流的特点
- 无法关闭
- 操作数据量小,效率高
- 一般操作临时文件
三、RandomAccessFile——随机访问流
1、写入单个字节
跟前面的 IO 流代码大同小异。
2、覆盖
回想前面写操作,可以发觉每次进行写操作时,都会清空里面的内容再写,但这个不同,每次写入从文件的头部开始覆盖原有的数据进行写入。
举例子:
先往里面写入 abc,再继续写个 1,看结果:
可以发觉,a 被覆盖成了 1。
3、seek——偏移量
通过指定光标的位置进行写入:可以通过操控光标位置,从某一位置开始往后进行写入:
然后,结果就会变成 1qc:
4、偏移量随写入而改变
每次写入以后,偏移量,也就是光标都会在最后面,只有重新运行时,光标才会从头写入。
意思是:写个 abc 以后,此时的光标在 c 后面,重新运行才会从头开始写;如果后面还有其他代码写入,则会从 c 以后写入。
5、读操作
注意:如果要读取 long 类型的数据,需要使用 readlong()方法去读。
6、断点续传
使用过迅雷下片的小伙伴都知道,当暂停下载,下次启动的时候,会继续下载,不需要从头下载,这就是断点续传了。
要实现断点续传,目的源和数据源的偏移量要一致。只需要把目的源的长度当做偏移量即可。
断点续传:
@Test
public void method3() throws IOException {
// 断点续传
RandomAccessFile r = new RandomAccessFile("test.png","r");
RandomAccessFile rw = new RandomAccessFile("test1.png","rw");
// 指定偏移量
r.seek(rw.length());
rw.seek(rw.length());
// 拷贝
byte[] b = new byte[1024];
int len;
while ((len = r.read(b)) != -1){
rw.write(b,0,len);
}
r.close();
rw.close();
}
经试验测试,拷贝多少就能看多少,比如一个视频,拷贝到一半停止,那么前面一半能正常观看。图像则是上面一半能看。
7、小结
- 只有一个类,由一个类创建不同的对象来实现输入和输出。
- 拥有指针(偏移量)。
- 每次实例化对象,不会清空文件,偏移量为0,从0开始覆盖写入或者读取。
- 可以实现在文件任意位置进行读写操作。