zoukankan      html  css  js  c++  java
  • javaday24_转换流_缓冲流_流的操作规律

    转换流:

    为什么有它?

    之前的里面的FileWriter  和 FileReader 类的时候,我们知道它们只能采用默认字符编码  和 默认字节缓冲区。

    所以我们这里介绍 转换流 它可以指定 字符编码,它能帮助我们解决 往后开发中遇到的乱码问题!

    转换流---OutputStreamWriter 类:

    文档里说它是 字符流通向字节流 的桥梁。它可以将字符流  转为 字节流。 因为文件的本质其实都是以字节存储的。

    注: 

    FileOutputStream是 字节流中的输出流 类! (写文件)

    FileInputStream 是 字节流中的输入流 类! (读文件)

    FileWriter 是 字符流 中的 文件写入方法!(写文件)

    FileReader 是 字符流 中的文件读出方法! (读文件)

    OutputStreamWriter : 新学的 转换流!它可以将 字符流 转为字节流!  

    OutputStreamWriter 的使用:

    两个构造函数,

    注:编码表 不区分大小写。 

     1 package cn.zcb.demo03;
     2 
     3 import java.io.FileOutputStream;
     4 import java.io.IOException;
     5 import java.io.OutputStreamWriter;
     6 
     7 public class Test {
     8     /*转换流 OutputStreamWriter  的使用*/
     9     public static void main(String[] args) throws IOException {
    10         //1,先创建一个  字节输出流(FileOutputStream ),待会 我们的转换流会 连接上它
    11         FileOutputStream fileOutputStream = new FileOutputStream("d:\test\a.txt");
    12 
    13         //2,创建转换流 并连接字节输出流
    14         OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"gbk"); //此时也可以省略不写,因为默认就是gbk
    15 
    16         //3,此时,如果通过转换流写入的 字符就会以转换流指定的编码形式写入到 字节输出流指定的文件中了。
    17         outputStreamWriter.write("我爱你中国!");
    18 
    19         outputStreamWriter.close();//此时,关闭转换流也同样会关闭 字节输出流!
    20     }
    21 }
    写入字符,并且以gbk形式字节保存文件
    package cn.zcb.demo03;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.OutputStreamWriter;
    
    public class Test {
        /*转换流 OutputStreamWriter  的使用*/
        public static void main(String[] args) throws IOException {
            //1,先创建一个  字节输出流(FileOutputStream ),待会 我们的转换流会 连接上它
            FileOutputStream fileOutputStream = new FileOutputStream("d:\test\a.txt");
    
            //2,创建转换流 并连接字节输出流
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"utf-8"); 
            
            //3,此时,如果通过转换流写入的 字符就会以转换流指定的编码形式写入到 字节输出流指定的文件中了。
            outputStreamWriter.write("我爱你中国!");
    
            outputStreamWriter.close();//此时,关闭转换流也同样会关闭 字节输出流!
        }
    }
    写入字符,以utf8 形式字节 保存文件

    注意:

    OutputStreamWriter 有个子类---FileWriter。(也就是我们的字符写入流)。

    二者的区别是后者不能更改编码表,只能使用默认的编码表来转换为字节;前者可以更改编码表!

    转换流---OutputStreamReader 类:

    它可以将字节流  转为字符流。  

    和 写入的时候一样,我们前面使用的读字符的类 FileReader 只能用于 默认编码。如果我们想使用其他编码来读文件。就要使用FileReader的父类OutputStreamReader的帮助了。 

    它类似于上面介绍的过程,它是先通过FileInputStream字节输入流 从文件中读入得到 相应的字节。 然后,它在通过制定的编码表 将字节转换为 字符输出! 

    它的构造函数,此时是多态!

     1 package cn.zcb.demo03;
     2 
     3 import java.io.FileInputStream;
     4 import java.io.IOException;
     5 import java.io.InputStream;
     6 import java.io.InputStreamReader;
     7 
     8 public class Test {
     9     /*转换流 OutputStreamWriter  的使用*/
    10     public static void main(String[] args) throws IOException {
    11         //1,先创建一个 字节输入流 ,从文件中读取相应的字节 出来, 待会我们的InputStreamReader会连接它。
    12         FileInputStream fileInputStream = new FileInputStream("d:\test\a(gbk 编码).txt");
    13 
    14         //2,创建转换流 InputStreamReader ,并连接 我们的字节输入流
    15         InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"gbk"); //gbk可以省略
    16 
    17         //3,此时,如果读取文件,就会以 转换流指定的编码  将文件中的字节   读取到程序中了。
    18         char[] arr = new char[1024];
    19         int ret = inputStreamReader.read(arr);  //因为我们知道一次一定可以读完,所以没有循环读取,如果不确定是否能读完,要进行循环读取
    20         System.out.println(arr);
    21 
    22         inputStreamReader.close(); //同时,用于连接的 字节输入流 也会被关闭
    23     }
    24 }
    从文件中读出 字节,然后 通过查询 gbk编码表 转换为字符输出!
     1 package cn.zcb.demo03;
     2 
     3 import java.io.FileInputStream;
     4 import java.io.IOException;
     5 import java.io.InputStreamReader;
     6 
     7 public class Test {
     8 
     9     /*转换流 OutputStreamWriter  的使用*/
    10     public static void main(String[] args) throws IOException {
    11         //1,先创建一个 字节输入流 ,从文件中读取相应的字节 出来, 待会我们的InputStreamReader会连接它。
    12         FileInputStream fileInputStream = new FileInputStream("d:\test\a(utf8 编码).txt");
    13 
    14         //2,创建转换流 InputStreamReader ,并连接 我们的字节输入流
    15         InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"utf8"); //gbk可以省略
    16 
    17         //3,此时,如果读取文件,就会以 转换流指定的编码  将文件中的字节   读取到程序中了。
    18         char[] arr = new char[1024];
    19         int ret = inputStreamReader.read(arr);  //因为我们知道一次一定可以读完,所以没有循环读取,如果不确定是否能读完,要进行循环读取
    20         System.out.println(arr);
    21 
    22         inputStreamReader.close(); //同时,用于连接的 字节输入流 也会被关闭
    23     }
    24 }
    从文件中读出 字节,然后 通过查询 utf8编码表 转换为字符输出

    转换流  的子类 父类的区别:

    转换流  OutputStreamWriter 和 InputStreamReader 两个可以指定编码表; 

    它们的子类 FileWriter  和 FileReader 两个只能是默认的编码表。 

    缓冲流:

    在流对象中,效率是个头疼的事情,我们上次的时候使用数组 提高了效率(不至于一次读一个,一次读一个数组 )。

    其实,系统中已经提供好了一套缓冲流,它们设计的目的就是为了提高IO操作速度。 

    缓冲流都是以 Buffered开头。

    四大缓冲流!

    字节缓冲流:

    BufferedOutputStream 字节缓冲 输出流

    它继承自OutputStream ,也是字节输出流。 起到缓冲作用。

     1 package cn.zcb.demo03;
     2 
     3 
     4 import java.io.BufferedOutputStream;
     5 import java.io.FileOutputStream;
     6 import java.io.IOException;
     7 
     8 public class Test {
     9     /*字节缓冲输出流的  的使用*/
    10     public static void main(String[] args) throws IOException {
    11         //1, 创建一个 字节输出流
    12         FileOutputStream fileOutputStream = new FileOutputStream("d:\test\c.txt");
    13         //2,创建一个字节缓冲输出流 它 可以提高 字节输出流写入文件的效率!
    14         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
    15 
    16         //3,使用字节缓冲输出流 提高字节输出流的 效率。 
    17         bufferedOutputStream.write("Hello 我爱你呀".getBytes());
    18 
    19         //4,关闭
    20         bufferedOutputStream.close(); //此时的 缓冲流也会被关闭 !
    21     }
    22 }
    使用字节缓冲输出流 提高字节输出流的 效率

    BufferedInputStream字节缓冲 输入流 

     1 package cn.zcb.demo03;
     2 
     3 
     4 import java.io.BufferedInputStream;
     5 import java.io.FileInputStream;
     6 import java.io.IOException;
     7 
     8 public class Test {
     9     /*字节缓冲输出流的  的使用*/
    10     public static void main(String[] args) throws IOException {
    11         //1, 创建一个 字节输入流
    12         FileInputStream fileInputStream = new FileInputStream("d:\test\c.txt");
    13         //2,创建一个字节缓冲输入流 它 可以提高 字节输入流 读取文件的效率!
    14         BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream); //里面是被提高效率的流。
    15 
    16         //3,使用buffer 提高 效率。
    17         byte[] b = new byte[1024];
    18         bufferedInputStream.read(b);  //这里我们知道一次可以读完!
    19         System.out.println(new String(b));
    20 
    21         //4,关闭
    22         bufferedInputStream.close(); //此时的 缓冲流也会被关闭 !
    23     }
    24 
    25 }
    使用字节缓冲输入流  提高字节输入流的效率 
     1 package cn.zcb.demo03;
     2 
     3 
     4 public class Test {
     5 
     6     public static void main(String[] args) {
     7         //我们一直使用的 System.in  我们发现 它是抽象类 InputStream 的子类的对象 。其实这个子类就是BufferedInputStream 类
     8         //证明如下:
     9         System.out.println(System.in); //java.io.BufferedInputStream@2d98a335
    10         //所以,我们在键盘输入的时候,传入 System.in 也是为了提高,字节输入流的效率的。
    11     }
    12 }
    System.in 其实就是BufferedInputStream 的对象,它就是通过字节缓冲 输入流 来提高 System.in的效率的!

    四种文件复制 效率比较:

     1 package cn.zcb.demo03;
     2 
     3 import java.io.*;
     4 import java.util.Arrays;
     5 
     6 public class Test {
     7     public static void main(String[] args) throws IOException{
     8         long begin_time = System.currentTimeMillis(); //毫秒值!
     9         function01(new File("d:\a.txt"),new File("e:\a.txt")); //文件大小为 2Mb
    10         long end_time1 = System.currentTimeMillis();
    11         System.out.println(end_time1 - begin_time);  //11388ms
    12 
    13         function02(new File("d:\a.txt"),new File("e:\a.txt")); //文件大小为 2Mb
    14         long end_time2 = System.currentTimeMillis();
    15         System.out.println(end_time2 - end_time1); //31ms
    16 
    17         function03(new File("d:\a.txt"),new File("e:\a.txt")); //文件大小为 2Mb
    18         long end_time3 = System.currentTimeMillis();
    19         System.out.println(end_time3 - end_time2); //32ms
    20 
    21         function04(new File("d:\a.txt"),new File("e:\a.txt")); //文件大小为 2Mb
    22         long end_time4 = System.currentTimeMillis();
    23         System.out.println(end_time4 - end_time3); //15ms
    24 
    25     }
    26     public static void function01(File src,File dest) throws IOException {
    27         /*第一种 字节流读写 单个字节*/
    28         FileInputStream fileInputStream = new FileInputStream(src); //读入
    29         FileOutputStream fileOutputStream  = new FileOutputStream(dest); //写出
    30         int ret;
    31         while ((ret = fileInputStream.read()) != -1){
    32             fileOutputStream.write(ret);
    33         }
    34         fileInputStream.close();
    35         fileOutputStream.close();
    36     }
    37     public static void function02(File src,File dest) throws IOException{
    38         /*第二种 字节流读写 字节数组*/
    39         FileInputStream fileInputStream = new FileInputStream(src); //读入
    40         FileOutputStream fileOutputStream  = new FileOutputStream(dest); //写出
    41         int ret;
    42         byte[] arr = new byte[1024];
    43         while ((ret = fileInputStream.read(arr)) != -1){
    44             fileOutputStream.write(arr);
    45             //清空 arr
    46             Arrays.fill(arr,(byte)0);
    47         }
    48         fileInputStream.close();
    49         fileOutputStream.close();
    50     }
    51     public static void function03(File src,File dest) throws IOException{
    52         /*第三种 字节缓冲流读写 单个字节 */
    53         FileInputStream fileInputStream = new FileInputStream(src);
    54         FileOutputStream fileOutputStream  = new FileOutputStream(dest);
    55         BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);  //读入
    56         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);  //写出
    57 
    58         int ret;
    59         while ((ret = bufferedInputStream.read()) != -1){
    60             bufferedOutputStream.write(ret);
    61         }
    62         bufferedInputStream.close();
    63         bufferedOutputStream.close();
    64 
    65     }
    66     public static void function04(File src,File dest) throws IOException{
    67         /*第四种 字节缓冲流读写 字节数组 */
    68         FileInputStream fileInputStream = new FileInputStream(src); //读入
    69         FileOutputStream fileOutputStream  = new FileOutputStream(dest); //写出
    70         BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);  //读入
    71         BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);  //写出
    72 
    73         int ret;
    74         byte[] arr = new byte[1024];
    75         while ((ret = bufferedInputStream.read(arr)) != -1){
    76             bufferedOutputStream.write(arr);
    77             //清空 arr
    78             Arrays.fill(arr,(byte)0);
    79         }
    80         bufferedInputStream.close();
    81         bufferedOutputStream.close();
    82     }
    83 
    84 
    85 }
    86 /*输出:
    87 11388
    88 31
    89 32
    90 15
    91 * */
    View Code

    所以,结果很明显,推荐使用缓冲流来 进行IO操作! 

    字符缓冲流:

    完成文本数据的高效的写入 与 读取的操作。 

    BufferedWriter 字符缓冲输出流

     1 package cn.zcb.demo03;
     2 
     3 import java.io.BufferedWriter;
     4 import java.io.FileWriter;
     5 import java.io.IOException;
     6 
     7 public class Test {
     8     /*字符缓冲输出流 的使用*/
     9     public static void main(String[] args) throws IOException {
    10         FileWriter fileWriter = new FileWriter("d:\d.txt");
    11         BufferedWriter bufferedWriter =new BufferedWriter(fileWriter); //使用buffered 提高了 fileWriter流的效率
    12 
    13         bufferedWriter.write(97); //写字符 a
    14         bufferedWriter.write("hello world".toCharArray());//写字符数组
    15         bufferedWriter.write("我爱你中国!"); //写字符串
    16 
    17         bufferedWriter.close();//此时,fileWriter也跟着 被关闭了 。
    18     }
    19 }
    20 /*输出:
    21 * */
    使用BufferedWriter 字符缓冲输出流 提高 字符输出流的效率!

    不过,这个BufferedWriter字符缓冲输出流,它具有一个自己特有的方法:void newLine()  .它的意思是写换行。  

    我们之前换行是使用 ,

    这个方法直接就是换行,而且关键的是它与平台无关。所以,建议使用newLine()  方法。 

     1 package cn.zcb.demo03;
     2 
     3 import java.io.BufferedWriter;
     4 import java.io.FileWriter;
     5 import java.io.IOException;
     6 
     7 public class Test {
     8     /*字符缓冲输出流 的使用*/
     9     public static void main(String[] args) throws IOException {
    10         FileWriter fileWriter = new FileWriter("d:\d.txt");
    11         BufferedWriter bufferedWriter =new BufferedWriter(fileWriter); //使用buffered 提高了 fileWriter流的效率
    12 
    13         bufferedWriter.write(97); //写字符 a
    14         bufferedWriter.newLine();
    15         bufferedWriter.write("hello world".toCharArray());//写字符数组
    16         bufferedWriter.newLine();
    17         bufferedWriter.write("我爱你中国!"); //写字符串
    18 
    19         bufferedWriter.close();//此时,fileWriter也跟着 被关闭了 。
    20     }
    21 }
    22 /*输出:
    23 * */
    .newLine() 的使用!

    BufferedReader 字符缓冲输入流  

    对于 读取一个字符  和  读取 字符数组,这里不说了。 

    它也有自己的一个特殊方法,就是可以一下读一个整行,并返回一个字符串。 String readLine();  它依靠的是  当遇到终止符(   ),停止读取;返回的字符串中不包含终止符。

    如果读到文件末尾,返回null 。 

     1 package cn.zcb.demo03;
     2 
     3 import java.io.BufferedReader;
     4 import java.io.FileReader;
     5 import java.io.IOException;
     6 
     7 public class Test {
     8     /*字符缓冲输入流 的使用*/
     9     public static void main(String[] args) throws IOException {
    10         FileReader fileReader = new FileReader("d:\d.txt");
    11 
    12         //创建字符缓冲输入流 BufferedReader
    13         BufferedReader bufferedReader = new BufferedReader(fileReader);
    14 
    15 //      1,  bufferedReader.read(); //读到 一个字符
    16 //      2,  bufferedReader.read(arr); //读到 一个字符数组中
    17 
    18 //      3,   BufferedReader 的特有方法: readLine();  读取行。
    19 //        String ret =  bufferedReader.readLine();
    20 //        System.out.println(ret);
    21         //循环 行读取
    22         String ret;
    23         while ((ret = bufferedReader.readLine()) != null){
    24             System.out.println(ret); //ret 为读取到 行 ,它是个字符串,而且它里面没有 任何终止符 存在!
    25         }
    26 
    27     }
    28 }
    29 /*输出:
    30 * */
    BufferedReader 字符缓冲输入流 的特有方法String readLine() 方法, 

    补充:

     

    注: BufferedReader 有个已知子类 LineNumberReader 它可以帮我们读取的内容实现 带有行号。 其实行号就是个计数器,我们也可以自己手动实现。  

     1 package cn.zcb.demo03;
     2 
     3 import java.io.FileReader;
     4 import java.io.IOException;
     5 import java.io.LineNumberReader;
     6 
     7 public class Test {
     8     /*字符缓冲输入流BufferedReader 的子类 LineNumberReader(带有行号) 的使用*/
     9     public static void main(String[] args) throws IOException {
    10         FileReader fileReader = new FileReader("d:\d.txt");
    11         LineNumberReader lineNumberReader = new LineNumberReader(fileReader );
    12 
    13         lineNumberReader.getLineNumber();
    14         String ret;
    15         while ((ret = lineNumberReader.readLine()) != null){
    16             System.out.println(lineNumberReader.getLineNumber()+" "+ret);
    17         }
    18     }
    19 }
    20 /*输出:
    21 1 a
    22 2 hello world
    23 3 我爱你中国!
    24 * */
    View Code

    但是,其实我们用一个变量做计数器就能实现这个功能。 

    字符缓冲流 复制文本文件:

     1 package cn.zcb.demo03;
     2 
     3 import java.io.*;
     4 
     5 public class Test {
     6     /*字符缓冲流  复制文件*/
     7     public static void main(String[] args) throws IOException {
     8         BufferedReader bufferedReader = new BufferedReader(new FileReader("d:\d.txt"));
     9         BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("e:\e.txt"));
    10 
    11         //循环 读取文本行,写文本行,最后再写换行。
    12         String ret;
    13         while ((ret = bufferedReader.readLine()) != null){
    14             bufferedWriter.write(ret); //写文本行。
    15             bufferedWriter.newLine();  //写 换行(因为读取到的是没有 终止符的)
    16         }
    17 
    18         bufferedReader.close();
    19         bufferedWriter.close();
    20     }
    21 }
    22 /*输出:
    23 1 a
    24 2 hello world
    25 3 我爱你中国!
    26 * */
    View Code

    但是,此时的问题是 复制后的文件会多两个字节。原因是多复制了一个空行。

    多了个空行对于文本文件来说,不算什么,

    但是对于图片,视频等文件来说,可能就打不开了。 这是个问题!

    流 的操作规律:

    IO 流的 四大抽象 基类:

    1, InputStream   2,   Reader 

    3,OutputStream 4,   Writer  

    所有的流都是它们的孩子。 

    四个明确:

    1,明确操作的是读取文件(1,2基类),还是写入文件(3,4基类)。

    2,明确操作的数据 是 字节还是字符。 字节(非文本)用(1,3基类),字符(文本文件)用(2,4基类)。 

    3,明确数据所在的具体设备

    源设备: 

    硬盘上文件, File开头的流。

    内存里数组,字符串,需要用到内存流,例如ByteArrayInputStream,等等,这里是从内存中读取数据,或写入到内存中。 

    键盘:System.in  流。 

    网络:Socket 流 

    目的设备: 

    硬盘上文件,File开头的 流 

    内存,数组,字符串,例如ByteArrayOutputStream

    屏幕:System.out 流。 

    网络 :Socket 流。

    4,明确是否需要额外功能,额外功能指

    需要进行转换吗?转换流。 InputStreamReader 和 OutputStreamWriter。

    需要提高 效率吗?  缓冲流 。BufferedXXX.  

    IO流的继承图:

    操作字节的流:


    InputStream  <-- FileInputStream(操作文件的字节输入流)   <--BufferedInputStream(提高 字节输入流的效率)

    OutputStream  <--FileOutputStream(操作文件的字节输出流) <--BufferedOutputStream(提高 字节输出流的效率)

    操作字符的流:

    Writer   <--  OutputStreamWriter(可以指定编码表) <--FileWriter(简便的 字符输出流)   

         <--  BufferedWriter(提高 字符输出流的 效率)

    Reader <-- InputStreamReader (可以指定编码表)  <--FileReader(简便的 字符输入流)  

                 <--  BufferedReader(提高 字符输入流的 效率)

  • 相关阅读:
    谁的朱砂痣染白了谁的白月光
    随机数
    常见面试简单汇总整理
    oss分页列举遍历文件创建软链接
    oss创建软链接
    看英文文档的好处
    js原型链相关
    js 中的this指向问题
    jquery.fn.init
    转载
  • 原文地址:https://www.cnblogs.com/zach0812/p/11958472.html
Copyright © 2011-2022 走看看