IO缓冲流与转换流

IO缓冲流

Java 的IO流按流向分为输入流和输出流,按流的性能,又可以将流分为节点流和处理流。

节点流

节点流:直接与数据源相连,读入或读出。
直接使用节点流,读写不方便,为了更快的读写文件,才有了处理流。

常用的节点流

  • 父 类 :InputStream 、OutputStream、 Reader、 Writer
  • 文 件 :FileInputStream 、 FileOutputStrean 、FileReader 、FileWriter 文件进行处理的节点流
  • 数 组 :ByteArrayInputStream、 ByteArrayOutputStream、 CharArrayReader 、CharArrayWriter 对数组进行处理的节点流(对应的不再是文件,而是内存中的一个数组)
  • 字符串 :StringReader、 StringWriter 对字符串进行处理的节点流
  • 管 道 :PipedInputStream 、PipedOutputStream 、PipedReader 、PipedWriter 对管道进行处理的节点流

处理流(使用装饰者模式)

处理流和节点流一块使用,在节点流的基础上,再套接一层,套接在节点流上的就是处理流。

BufferedReader.处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

常用的处理流

  • 缓冲流:BufferedInputStream 、BufferedOutputStream、 BufferedReader、 BufferedWriter 增加缓冲功能,避免频繁读写硬盘。
  • 转换流:InputStreamReader 、OutputStreamReader实现字节流和字符流之间的转换。
  • 数据流: DataInputStream 、DataOutputStream 等-提供将基础数据类型写入到文件中,或者读取出来。

 

输入字节缓存流BufferedInputStream /输出字节缓冲流BufferedOutputStream

BufferedOutputsStream,BufferedInputStream都要包上一层节点流。

也就是说处理流是在节点流的基础之上进行的,带有Buffered的流又称为缓冲流,缓冲流处理文件的输入输出的速度是最快的。所以一般缓冲流的使用比较多。

我们将之前使用节点流改成缓冲流,提高性能。

 

字节输入流InputStream/字节输出流OutputStream

从文件向程序冲写数据使用InputStream的FileInputStream,按字节数组读取,使用处理流BufferedInputStream包装

 1 package com.sxt.io;
 2 
 3 import java.io.BufferedInputStream;
 4 import java.io.File;
 5 import java.io.FileInputStream;
 6 import java.io.FileNotFoundException;
 7 import java.io.IOException;
 8 import java.io.InputStream;
 9 
10 /**
11  * 四个步骤: 分段读取 文件字节输入流  加入缓冲流
12  * 1、创建源
13  * 2、选择流
14  * 3、操作
15  * 4、释放资源
16  * 
17  * @author liuzeyu12a
18  *
19  */
20 public class BufferedTest01 {
21 
22     public static void main(String[] args) {
23         File src = new File("abc.txt");
24         //2、选择流
25         InputStream  is =null;
26         try {
27             is =new BufferedInputStream(new FileInputStream(src));
28             //3、操作 (分段读取)
29             byte[] flush = new byte[1024]; //缓冲容器
30             int len = -1; //接收长度
31             while((len=is.read(flush))!=-1) {
32                 //字节数组-->字符串 (解码)
33                 String str = new String(flush,0,len);
34                 System.out.println(str);
35             }        
36         
37         } catch (FileNotFoundException e) {
38             e.printStackTrace();
39         } catch (IOException e) {
40             e.printStackTrace();
41         }finally {
42             //4、释放资源
43             try {
44                 if(null!=is) {
45                     is.close();
46                 }
47             } catch (IOException e) {
48                 e.printStackTrace();
49             }            
50         }
51     }
52     
53     public static void test1() {
54         //1、创建源
55         File src = new File("abc.txt");
56         //2、选择流
57         InputStream  is =null;
58         BufferedInputStream bis =null;
59         try {
60             is =new FileInputStream(src);
61             bis = new BufferedInputStream(is);
62             //3、操作 (分段读取)
63             byte[] flush = new byte[1024]; //缓冲容器
64             int len = -1; //接收长度
65             while((len=is.read(flush))!=-1) {
66                 //字节数组-->字符串 (解码)
67                 String str = new String(flush,0,len);
68                 System.out.println(str);
69             }                
70         } catch (FileNotFoundException e) {
71             e.printStackTrace();
72         } catch (IOException e) {
73             e.printStackTrace();
74         }finally {
75             //4、释放资源
76             try {
77                 if(null!=is) {
78                     is.close();
79                 }
80             } catch (IOException e) {
81                 e.printStackTrace();
82             }
83             try {
84                 if(null!=bis) {
85                     bis.close();
86                 }
87             } catch (IOException e) {
88                 e.printStackTrace();
89             }
90         }
91     }
92 
93 }
View Code

从程序向文件中写数据使用OutputStream的FileOutputStream,按字节数组写入,使用处理流BufferedOutputsStream包装

 1 package com.sxt.io;
 2 
 3 import java.io.BufferedOutputStream;
 4 import java.io.File;
 5 import java.io.FileNotFoundException;
 6 import java.io.FileOutputStream;
 7 import java.io.IOException;
 8 import java.io.OutputStream;
 9 
10 /**
11  * 文件字节输出流  加入缓冲流
12  *1、创建源
13  *2、选择流
14  *3、操作(写出内容)
15  *4、释放资源
16  * @author liuzeyu12a
17  *
18  */
19 public class BufferedTest02 {
20 
21     public static void main(String[] args) {
22         //1、创建源
23         File dest = new File("dest.txt");
24         //2、选择流
25         OutputStream os =null;
26         try {
27             os =new BufferedOutputStream( new FileOutputStream(dest));
28             //3、操作(写出)
29             String msg ="IO is so easy\r\n";
30             byte[] datas =msg.getBytes(); // 字符串-->字节数组(编码)
31             os.write(datas,0,datas.length);
32             os.flush();
33         }catch(FileNotFoundException e) {        
34             e.printStackTrace();
35         }catch (IOException e) {
36             e.printStackTrace();
37         }finally{
38             //4、释放资源
39             try {
40                 if (null != os) {
41                     os.close();
42                 } 
43             } catch (Exception e) {
44             }
45         }
46     }
47 
48 }
View Code

一个简单的案例:实现音频的复制粘贴

代码:

 1 package com.sxt.io;
 2 
 3 import java.io.BufferedInputStream;
 4 import java.io.BufferedOutputStream;
 5 import java.io.File;
 6 import java.io.FileInputStream;
 7 import java.io.FileNotFoundException;
 8 import java.io.FileOutputStream;
 9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.OutputStream;
12 
13 /**
14  * 文件拷贝:文件字节输入、输出流
15  *
16  *  @liuzeyu12a
17  *
18  */
19 public class Copy {
20 
21     public static void main(String[] args) {
22         long t1 = System.currentTimeMillis();
23         copy("IO开篇.mp4","IO-copy.mp4"); 
24         long t2 = System.currentTimeMillis();
25         System.out.println(t2-t1);
26     }
27     
28     public static void copy(String srcPath,String destPath) {
29         //1、创建源
30             File src = new File(srcPath); //源头
31             File dest = new File(destPath);//目的地
32             //2、选择流        
33             try( InputStream is=new BufferedInputStream(new FileInputStream(src));
34                     OutputStream os =new BufferedOutputStream( new FileOutputStream(dest));    ) {                
35                 //3、操作 (分段读取)
36                 byte[] flush = new byte[1024]; //缓冲容器
37                 int len = -1; //接收长度
38                 while((len=is.read(flush))!=-1) {
39                     os.write(flush,0,len); //分段写出
40                 }            
41                 os.flush();
42             }catch(FileNotFoundException e) {        
43                 e.printStackTrace();
44             }catch (IOException e) {
45                 e.printStackTrace();
46             }
47     }
48 }
View Code

字符输入流 Reader/字符输出流Writer

从文件向程序冲写数据使用Reader的FileReader,按字符数组读取,使用BufferedReader包装

 1 package com.sxt.io;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.File;
 5 import java.io.FileNotFoundException;
 6 import java.io.FileReader;
 7 import java.io.IOException;
 8 
 9 /**
10  * 四个步骤: 分段读取 文件字符输入流  加入缓冲流
11  * 1、创建源
12  * 2、选择流
13  * 3、操作
14  * 4、释放资源
15  * 
16  * @author liuzeyu12a
17  *
18  */
19 public class BufferedTest03 {
20 
21     public static void main(String[] args) {
22         //1、创建源
23         File src = new File("abc.txt");
24         //2、选择流
25         BufferedReader  reader =null;
26         try {
27             reader =new BufferedReader(new FileReader(src));
28             //3、操作 (分段读取)
29             String line =null;
30             while((line=reader.readLine())!=null) {
31                 //字符数组-->字符串
32                 System.out.println(line);
33             }        
34         
35         } catch (FileNotFoundException e) {
36             e.printStackTrace();
37         } catch (IOException e) {
38             e.printStackTrace();
39         }finally {
40             //4、释放资源
41             try {
42                 if(null!=reader) {
43                     reader.close();
44                 }
45             } catch (IOException e) {
46                 e.printStackTrace();
47             }
48         }
49     }
50 
51 }
View Code

从文件向程序冲写数据使用Writer的FileWriter,按字符数组写出,使用BufferedWriter包装

 1 package com.sxt.io;
 2 
 3 import java.io.BufferedWriter;
 4 import java.io.File;
 5 import java.io.FileNotFoundException;
 6 import java.io.FileWriter;
 7 import java.io.IOException;
 8 
 9 /**
10  * 文件字符输出流 加入缓冲流
11  *1、创建源
12  *2、选择流
13  *3、操作(写出内容)
14  *4、释放资源
15  * @author liuzeyu12a
16  *
17  */
18 public class BufferedTest04 {
19 
20     public static void main(String[] args) {
21         //1、创建源
22         File dest = new File("dest.txt");
23         //2、选择流
24         BufferedWriter writer =null;
25         try {
26             writer = new BufferedWriter(new FileWriter(dest));
27             //3、操作(写出)            
28             writer.append("IO is so easy");
29             writer.newLine();
30             writer.append("尚学堂欢迎你");
31             writer.flush();
32         }catch(FileNotFoundException e) {        
33             e.printStackTrace();
34         }catch (IOException e) {
35             e.printStackTrace();
36         }finally{
37             //4、释放资源
38             try {
39                 if (null != writer) {
40                     writer.close();
41                 } 
42             } catch (Exception e) {
43             }
44         }
45     }
46 
47 }
View Code

字符缓存流文件的拷贝

代码:

 1 package com.sxt.io;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.BufferedWriter;
 5 import java.io.File;
 6 import java.io.FileNotFoundException;
 7 import java.io.FileReader;
 8 import java.io.FileWriter;
 9 import java.io.IOException;
10 /**
11  * 文件拷贝:文件字节输入、输出流
12  *
13  *  @author liuzeyu12a
14  *
15  */
16 public class CopyTxt {
17 
18     public static void main(String[] args) {
19         copy("abc.txt","abc-copy.txt"); 
20     }    
21     public static void copy(String srcPath,String destPath) {
22         //1、创建源
23             File src = new File(srcPath); //源头
24             File dest = new File(destPath);//目的地
25             //2、选择流        
26             try( BufferedReader br=new BufferedReader(new FileReader(src));
27                     BufferedWriter bw =new BufferedWriter( new FileWriter(dest));    ) {                
28                 //3、操作 (逐行读取)
29                 String line =null;
30                 while((line=br.readLine())!=null) {
31                     bw.write(line); //逐行写出
32                     bw.newLine();
33                 }            
34                 bw.flush();
35             }catch(FileNotFoundException e) {        
36                 e.printStackTrace();
37             }catch (IOException e) {
38                 e.printStackTrace();
39             }
40     }
41 }
View Code

转换流

 

InputStreamReader和OutputStreamWriter是字符和字节的桥梁,也可称之为字符转换流。原理:字节流+编码。

InputStreamReader 、OutputStreamWriter 要InputStreamOutputStream作为参数,实现从字节流到字符流的转换。

构造函数

  InputStreamReader(InputStream);        //通过构造函数初始化,使用的是本系统默认的编码表GBK。
  InputStreamWriter(InputStream,String charSet);   //通过该构造函数初始化,可以指定编码表。   OutputStreamWriter(OutputStream); //通过该构造函数初始化,使用的是本系统默认的编码表GBK。   OutputStreamwriter(OutputStream,String charSet); //通过该构造函数初始化,可以指定编码表。

特点:

  1、转换流是字符流与字节流之间的桥梁

  2、可对读取到的字节指定编码转换成字符

  3、可对读取到的字符指定编码转换成字节

何时使用转换流?

    1、当字节和字符之间有转换动作时

    2、流操作的数据需要编码与解码时

 

    3、FileReader和FileWriter作为子类,仅作为操作字符文件的便捷类存在。当操作的字符文件,使用的是默认编码表时可以不用父类,而直接使用子类完成操作,简化代码。

 

一旦要指定其他编码时,不能使用子类,必须使用字符转换流。

 

操作的具体的类

    InputStreamReader:字节流到字符流之间的转换

    OutputStreamReader:字符流到字节流之间的转换

 

 Public class InputStreamReader extends Reader

(1)InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符。它使用的字符集可以由名称指定或显式给定,或者可以接受平台默认的字符集。

(2)每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。

(3)为了达到最高效率,可以考虑在 BufferedReader 内包装 InputStreamReader。例如:

 

   BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));   //重要

 

 public class OutputStreamWriter extends Writer

(1)OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的 charset 将要写入流中的字符编码成字节。它使用的字符集可以由名称指定或显式给定,否则将接受平台默认的字符集。

(2)每次调用 write() 方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。可以指定此缓冲区的大小,不过,默认的缓冲区对多数用途来说已足够大。注意,传递给 write() 方法的字符没有缓冲。

(3)为了获得最高效率,可考虑将 OutputStreamWriter 包装到 BufferedWriter 中,以避免频繁调用转换器。例如:

  BufferedWriter writer = new BufferedWriter(new OutputStreamReader(System.out));   //重要

 转换流的简单使用:利用标准输入流将文本输出到控制台

代码:

 1 package io深入学习;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.BufferedWriter;
 5 import java.io.IOException;
 6 import java.io.InputStreamReader;
 7 import java.io.OutputStreamWriter;
 8 
 9 /**
10  * 转换流:
11  * 1、字节流(全是纯文本内容)--->字符(解码)
12  * 2、指定字符集
13  * @author liuzeyu12a
14  *
15  */
16 public class ConvertStream {
17 
18     public static void main(String[] args) {
19         test02();
20     }
21     public static void test01() {
22         //操作System.in字节输入流,System.out字节输出流
23         try(InputStreamReader reader = new InputStreamReader(System.in);
24                 java.io.OutputStreamWriter write = new java.io.OutputStreamWriter(System.out)){
25             
26         }catch(Exception e) {
27             System.out.println("操作异常");
28         }
29     }
30     //加上缓存区,字符输入--->(程序处理)字节---->字符输出
31     public static void test02() {
32         //操作System.in字节输入流,System.out字节输出流
33         try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
34                 BufferedWriter write = new BufferedWriter(new OutputStreamWriter(System.out))){
35             
36             //循环获取键盘的输入
37             String msg="";
38             while(!msg.equals("exit")) {
39                 msg=reader.readLine();
40                 write.write(msg);
41                 //小文本需要强制刷新
42                 write.flush();
43             }
44         }catch(IOException e) {
45             System.out.println("操作异常");
46         }
47     }
48 }
View Code

拓展:网络爬虫的简单应用

通过网络流(字节流)--->向字符流的转换,从百度上爬取源码:

代码:

 1 package io深入学习;
 2 
 3 import java.io.BufferedReader;
 4 import java.io.BufferedWriter;
 5 import java.io.FileOutputStream;
 6 import java.io.InputStream;
 7 import java.io.InputStreamReader;
 8 import java.io.OutputStreamWriter;
 9 import java.net.URL;
10 
11 /**
12  * 转换流:
13  * 1、字节流(全是纯文本内容)--->字符(解码)
14  * 2、指定字符集
15  * @author liuzeyu12a
16  *
17  */
18 public class ConvertStream2 {
19     
20     public static void main(String[] args) {
21         //test02();
22         test03();
23     }
24     
25     public static void test01() {
26         //获取网络字节流
27         try(InputStream is =new URL("http://www.baidu.com").openStream()){
28             int temp = 0;
29             while((temp = is.read())!=-1) {
30                 System.out.print((char)temp);  //字节数不够出现乱码
31             }
32             
33         }catch(java.io.IOException e) {
34             e.printStackTrace();
35         }
36     }
37     
38     //爬取百度的源码
39     public static void test02() {
40         //获取网络字符流
41         //这边百度源码采用UTF-8,而工程的字符采用GBK,为了不造成乱码,于是可以指定字符集
42         try(InputStreamReader reader =new InputStreamReader(
43                 new URL("http://www.baidu.com").openStream(),"UTF-8")){
44             int temp = 0;
45             while((temp = reader.read())!=-1) {
46                 System.out.print((char)temp);
47             }
48             
49         }catch(java.io.IOException e) {
50             e.printStackTrace();
51         }
52     }
53     //爬取百度的源码,+缓冲
54     public static void test03() {
55         //获取网络字符流
56         //这边百度源码采用UTF-8,而工程的字符采用GBK,为了不造成乱码,于是可以指定字符集
57         try(BufferedReader reader =new BufferedReader(
58                 new InputStreamReader(
59                         new URL("http://www.baidu.com").openStream(),"UTF-8"));
60             BufferedWriter write =
61                     new BufferedWriter(new OutputStreamWriter(
62                             new FileOutputStream("baidu.html"),"UTF-8"))){
63             
64             String line = null;
65             while((line = reader.readLine())!=null) {
66                 write.write(line);
67             }
68             
69         }catch(java.io.IOException e) {
70             e.printStackTrace();
71         }
72     }
73 }
View Code

部分文字图片参考

jdk 1.60 开发文档

https://www.cnblogs.com/hopeyes/p/9736642.html

https://www.cnblogs.com/zhaoyanjun/p/6292384.html

 

转载于:https://www.cnblogs.com/liuzeyu12a/p/10397817.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值