• 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
    ";
    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

  • 相关阅读:
    通过jsonp解决ajax的跨域请求问题
    为php安装redis扩展模块并测试
    浅谈使用 PHP 进行手机 APP 开发(API 接口开发)(转)
    touch事件记录
    jquery mobile 问题
    background总结,转自http://www.daqianduan.com/3302.html
    博客收集
    css3 border-radius 总结
    css3 box-shadow 总结
    angular 重置表单
  • 原文地址:https://www.cnblogs.com/liuzeyu12a/p/10397817.html
Copyright © 2020-2023  润新知