输入流和输出流
输入流和输出流
关于输入和输出这2个总是有点模糊。
以内存为基准,输入流是文件流向内存,就是从文件中读取数据。输出流是从内存中流向文件,就是向文件中写入数据。
输入流
输入流又分为字节输入流InputStream和字符输入流Reader。
由于InputStream是抽象类,不能直接创建其对象,只能创建其子类的对象。比如FileInputStream类。Reader也同理。
字符流底层也是字节流,默认也是一个一个字节读取的,如果遇到中文,GBK一次读取2个字节,UTF-8一次读取3个字节。
使用都是3个步骤:
- 创建对象
- 读取数据
- 释放资源
一、创建对象时的2个细节
- 传递的参数既可以是字符串格式的,也可以是File对象。
- 读取的文件不存在会报错。
二、读取数据有两个方法
1、空参的read()
字节流一次读取一个字节,字符流一次读取一个字符。
返回值都是读取的字节解码转换成的十进制,即字符所在字符集中对应的码点。
2、有参的read(byte[] buffer)和read(char[] cbuf)
字节流一次读取多个字节放到数组中,字符流一次读取多个字符放到数组中。
字节流中的数组中存的是读取的字节解码转换成的十进制,即字符在字符集中所对应的码点,而字符数组中存的直接是字符。
同时要注意两个数组一个是byte类型的,一个是char类型。
三、释放资源
一般先开的资源最后释放。而且如果不释放资源,资源会一直被Java占用。
输出流
使用也是3个步骤:
- 创建对象
- 写入数据
- 释放资源
一、创建对象时的3个细节
- 传递的参数既可以是字符串格式的,也可以是File对象。
- 如果要写入的文件不存在则会创建出来,但是父级目录一定要存在。
- 在向本地文件中写入数据时,默认是清空原来文件中的所有内容,如果不想清空那么在创建IO流对象时可以传递true过去,即打开续写。
二、写入数据有很多方法
字节输出流和字符输出流的写出方法几乎都不太相同,所以分开介绍。
1、字节输出流
字节输出流需将字符转换为字符集中对应的码点再写入。
(1)write(int b):此方法中形参是int整数,但是实际往文件中写入数据时却不是整数,而是整数所对应的ASCII码表中的字符。
如果想写整数97呢?解决办法就是先写字符9,再写字符7。
(2)write(byte[] bytes)
(3)write(byte[] bytes,int off,int len):off表示写入数据的起始索引,len表示写入数据的长度。当然说的是bytes数组中的。
write方法接收的参数都是整数,但如果我们想写一个字符串过去,可以使用getBytes()方法将字符串转换为byte的数组。
想换行就把换行符\r\n写过去。
2、字符输出流
字符输出流可以直接将字符写入。
(1)写出字符:write(int b),每次可以写出一个字符数据,与字节输出流一样。
(2)写出字符数组:write(char[] cbuf) 和 write(char[] cbuf, int off, int len) ,每次可以写出字符数组中的数据,用法类似FileOutputStream。
(3)写出字符串: write(String str) 和 write(String str, int off, int len),每次可以写出字符串中的数据,更为方便。
三、释放资源
同输入流。
字节流和字符流的应用场景
字节流
拷贝任意类型的文件,比如图像、音频等等都可以。
字符流
读取和写入纯文本文件时使用字符流。