学习笔记——IO流
IO流主要分为字节流和字符流,流动方式分为输入和输出。
-
输入流中主要就是学习 读取的方法 read
-
输出流中主要就是学习 写出的方法 write
字节流
字节输入流 FileInputStream
-
FileInputStream(File file) 表示从 file 指向的文件中读取
-
FileInputStream(String name) name 表示文件的路径名(路径+文件名)
使用方式:
-
int read()
调用一次读到一个数据字节,返回的 int 值就是读到的数据
如果已到达文件末尾,则返回 -1。
-
int read(byte[] b)
调用一次本方法表示可以读取多个数据
读到的内容保存传入的 byte 数组 b 中
返回的是本次调用方法读到的数据字节个数
思考?b 数组是有长度,干嘛还要单独返回读到的个数呢?b数组是表示声明的用来存储读取的字节数据,但是实际并不一定能装满数组,所以返回的int表示一次读取实例存储的字节个数。
比如流中一共1028个字节,定义的b组容量为1024,那你就得读两次,但是第二次只读了4个字节,所以实例返回的int就是4。
-
int read(byte[] b, int off, int len)
和上面的第二个类似,可以指定从 b 数组什么位置开始装
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream(new File("a.txt"));
byte[] arr = new byte[10];
int len;
while ((len = fis.read(arr)) != -1) {
System.out.println(new String(arr,0,len));
}
fis.close();
}
乱码怎么产生的:
-
编码和解码规则不一致
-
本身这个字符编码不支持某种语言(中文)
-
read()无参默认读取一个字节,英文下字符是一个字节,不会乱码,但utf-8下中文 4个
-
读到半个中文字节,数据不完整,转成char就显示不了,乱码了。
-
字节流不太适合读文本。
字节输出流 FileOutputStream
通过输出流来把数据写入到文件中,实现将代码中的数据保存到记事本文件中。
new FileOutputStream("my.txt") 和 new FileOutputStream("my.txt",true) 区别是替换文本内容还是在后面添加内容。
注意: FileOutputStream 会自动创建一个文件(如果文件不存在,并且文件的路径存在的)
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("my.txt",true);
fos.write("空我".getBytes());
fos.close();
}
文件复制:
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("aa.jpg");
FileOutputStream fos = new FileOutputStream(new File("aaq.jpg"));
byte[] arr = new byte[10];
int len;
while ((len = fis.read(arr)) != -1) {
fos.write(arr, 0, len);
}
fos.close();
fis.close();
}
应用:文件加密;网络资源下载;文件转编码;音频拼接……
文件复制等流程:读流,并将读出来的数据写入新的文本中,应该弄一的输出流,一个输入流,输出流read()遍历读流,在循环中调用输入流write()写流。
字符流
使用字节流来操作中文的时候非常不方便,容易产生乱码,它不管你是哪种编码方式都按照一个字符一 个字符的方式读取数据。
字符流主要用来操作文本文件。可以复制文本,不能复制图片。
文件输入流 FileReader
FileReader的构造方法和方法与字节流输入流 FileInputStream 非常类似,差别就是单位是 char。
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("a.txt");
char[] arr = new char[1024*10];
int len ;
while ((len= fr.read(arr))!=-1){
System.out.println(new String(arr,0,len));
}
fr.close();
}
文件输出流 FileWriter
特有的方法: 可以直接写字符串
注意要关闭流,不然可能会写不进去。
字节流和字符流的区别
-
操作的单位不一样,一个是字节,一个是字符
-
操作中文的时候使用字符流更方便, 字节流更广泛:文本,视频,音频,图片...
-
字符流中有可以直接写字符串的方法
-
字节输出流 : 程序 ---> 磁盘文件 如果不关闭流也会写入
字符输出流 : 程序 ---> 缓冲 ---> 磁盘文件 如果不关闭流或者刷新缓冲区,不会写入文件
字符输出流,关闭的时候会先刷新,关闭之后不能够在操作,刷新之后可以继续操作
什么时候会用到刷新 : 写入的数据,比较多,可以在中途手动调用刷新的方法提交数据
转换流
如实现一个方法内部的代码,但是方法的结构式写好了的,如果我们需要覆写方法内部需要处理文本, 那么覆写的方法,方法参数改不了。所以可以在覆写的时候方法体将字节流参数,转换成字符流使用。
网络中传输基本都是字节流,如果传输的是文本,用字节操作不太方便,这个时候可以用转换流转成字符流来操作文本。
字节流转字符流 InputStreamReader
FileInputStream fis = new FileInputStream("a.txt");
InputStreamReader isr = new InputStreamReader(fis);
字符流转字节流 OutputStreamWriter
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a21a.txt"));
osw.write("kkk");
osw.close();
将字符"kkk"存在字节流a21a.txt里面
字符流一定要关流,不然文字不会写入进去
缓冲流
之前循环独写数据,操作磁盘的次数非常多,影响性能,通过缓冲流,可以先缓存大量读写数据,等到比较多了之后,在连接磁盘一次从磁盘读取或者写。避免多次连接磁盘影响性能。
其实用起来的话,跟上面的差不多,性能会相对更好。
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("a.png"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("aa.png"));
int len;
byte[] arr = new byte[1024 * 10];
while ((len = bis.read(arr))!=-1){
// System.out.println(new String(arr,0,len));
bos.write(arr,0,len);
}
bos.close();
bis.close();
long end = System.currentTimeMillis();
System.out.println(end-start);
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("aa.txt"));
String s;
while ((s = br.readLine()) != null) {
bw.write(s);
bw.newLine();
}
bw.close();
br.close();
}
为了防止程序运行中产生异常而导致流没有关闭,不对异常进行处理随意抛出是不合理的,所以应该对异常进行捕获,将对流的关闭操作放在finally中,确保流每次都会关闭。
对于java7新方式:自动关闭的流资源,必须是实现了AutoCloseable
小结
-
IO 流操作一般都应该关闭;
-
就算读写过程中产生了异常,最后也应该关闭,所有关闭流资源的代码一般放在 finally 结构中
-
Java7 新结构支持自动关闭,但是 try 的()中创建流的对象的流必须是支持自动关闭的(不过一般我
们用到的 IO 流都是有实现此接口的,以防万一,最好看一下Api文档)

浙公网安备 33010602011771号