JAVA:IO流之节点流与处理流

1. 流的分类

  • 按数据流的方向不同:输入流,输出流。
  • 按处理数据单位不同:字节流,字符流。
    (1) 字节流:数据流中最小的数据单元是字节。
    (2)字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。
  • 按功能不同:节点流,处理流。
    (1)程序用于直接操作目标设备所对应的类叫节点流。
    (2)程序通过一个间接流类去调用节点流类,以达到更加灵活方便地读写各种类型的数据,这个间接流类就是处理流。

2. 节点流

2.1 节点流的类型

这里写图片描述

  • (1)File 文件流。对文件进行读、写操作 :FileReader、FileWriter、FileInputStream、FileOutputStream。、
  • (2)Memory
    1)从/向内存数组读写数据: CharArrayReader与 CharArrayWriter、ByteArrayInputStream与ByteArrayOutputStream。
    2)从/向内存字符串读写数据 StringReader、StringWriter、StringBufferInputStream。
  • (3)Pipe管道流。 实现管道的输入和输出(进程间通信): PipedReader与PipedWriter、PipedInputStream与PipedOutputStream。

2.2 节点流执行的图示

这里写图片描述

3. 处理流

3.1 处理流的类型

这里写图片描述
- (1)Buffering缓冲流:在读入或写出时,对数据进行缓存,以减少I/O的次数:BufferedReader与BufferedWriter、BufferedInputStream与BufferedOutputStream。
- (2)Filtering 滤流:在数据进行读或写时进行过滤:FilterReader与FilterWriter、FilterInputStream与FilterOutputStream。
- (3)Converting between Bytes and Characters 转换流:按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换(Stream到Reader):InputStreamReader、OutputStreamWriter。
- (4)Object Serialization 对象流 :ObjectInputStream、ObjectOutputStream。
- (5)DataConversion数据流: 按基本数据类型读、写(处理的数据是Java的基本类型(如布尔型,字节,整数和浮点数)):DataInputStream、DataOutputStream 。
- (6)Counting计数流: 在读入数据时对行记数 :LineNumberReader、LineNumberInputStream。
- (7)Peeking Ahead预读流: 通过缓存机制,进行预读 :PushbackReader、PushbackInputStream。
- (8)Printing打印流: 包含方便的打印方法 :PrintWriter、PrintStream。

3.2 处理流执行的图示

这里写图片描述

3.3 缓冲流

  • 【1】对I/O进行缓冲是一种常见的性能优化,缓冲流为I/O流增加了内存缓冲区,增加缓冲区的两个目的:
    (1)允许Java的I/O一次不只操作一个字符,这样提高䇖整个系统的性能;
    (2)由于有缓冲区,使得在流上执行skip、mark和reset方法都成为可能。

  • 【2】缓冲流:它是要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,
    提高了读写的效率,同时增加了一些新的方法。例如:BufferedReader中的readLine方法,
    BufferedWriter中的newLine方法。

  • 【3】J2SDK提供了4种缓存流,常用的构造方法为:

//字符输入流
BufferedReader(Reader in)//创建一个32字节的缓冲区
BufferedReader(Reader in, int size)//size为自定义缓存区的大小

//字符输出流
BufferedWriter(Writer out)
BufferedWriter(Writer out, int size)

//字节输入流
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size)

//字节输出流
BufferedOutputStream(OutputStream in)
BufferedOutputStream(OutputStream in, int size)
 
 
  • 【4】其他
    (1)缓冲输入流BufferedInputSTream除了支持read和skip方法意外,还支持其父类的mark和reset方法;
    (2)BufferedReader提供了一种新的ReadLine方法用于读取一行字符串(以\r或\n分隔);
    (3)BufferedWriter提供了一种新的newLine方法用于写入一个行分隔符;
    (4)对于输出的缓冲流,BufferedWriter和BufferedOutputStream,写出的数据会先在内存中缓存,
    使用flush方法将会使内存的数据立刻写出。

  • 示例1:

import java.io.*;
public class TestBufferStream1 {
  public static void main(String[] args) {
    try {
      FileInputStream fis = new FileInputStream(
          "d:\\JavaProject\\demo13\\ProcessingStream\\TestBufferStream1.java");
      BufferedInputStream bis = new BufferedInputStream(fis);
      int c = 0;
      System.out.println((char)bis.read());
      System.out.println((char)bis.read());
      bis.mark(100);/*在当前输入流的当前位置上做一个标志,允许最多再读入100个字节*/
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){
        System.out.print((char)c+" ");
      }
      System.out.println(); 
      bis.reset();/*把输入指针返回到以前所做的标志处*/
      for(int i=0;i<=10 && (c=bis.read())!=-1;i++){
        System.out.print((char)c+" ");
      }
      bis.close();
    } catch (IOException e) {e.printStackTrace();}
  }
}
  
  
  • 示例2:
import java.io.*;
public class TestBufferStream2
{
    public static void main(String[] args)
    {
    try{
    BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt"));
    BufferedReader br = new BufferedReader(new FileReader("D:\\JavaProject\\demo13\\BufferStream\\dat2.txt"));
    String s = null;
    for(int i=0;i<10;i++)
    {
        s = String.valueOf(Math.random());//产生一个小于1的正的随机数,并转换成字符串形式
        bw.write(s);//把字符串s写入到dat2.txt文件中
        bw.newLine();//写入一个行分隔符
    }
    bw.flush();//使用flush方法将会使内存的数据立刻写出

    while((s=br.readLine()) != null)
    {
        System.out.println(s);
    }
    bw.close();
    br.close();
    }
    catch(IOException e)
    {
        e.printStackTrace();
    }

    }
}
   
   

3.4 转换流

  • 转换流有两种:
    (1)InputStreamReader:将字节流转换为字符流;
    (2)OutputStreamWriter:将字符流转换为字节流。
  • 什么时候使用转换流?由以下分析: 流对象很多,就要明确使用哪个流对象。
通过三点来完成: 
    1、明确数据的来源和数据到达的目的地。
                 来源:输入流 [InputStream,Reader]。 
                 目的:输出流 [OutputStream,Writer]。 
    2、操作的数据是否是纯文本。  
                 是:字符流,使用Reader与Writer; 
                 否:字节流,使用InputStreamOutputStream3、明确要使用哪个具体的对象。 通过设备来进行区分: 
                 源设备:内存用数组,硬盘就加file,键盘用System.in; 
                 目的设备:内存用数组,硬盘就加file,键盘用System.out。 
    4、明确是否还需要其他额外功能:例如 
                (1)是否需要较高的效率,即是否需要使用缓冲区,是就加上Buffered;
                (2)是否需要转换,是,就使用转换流,InputStreamReader 和 OutputStreamWriter。
    
    
  • 用一个例子简单的说明: 将键盘录入的数据保存到一个文件中,输入“over”时表示录入结束。 详细分析:
源:从InputStream,Reader中选择; 因为是键盘录入的是纯文本,所以使用Reader。 
设备:键盘,所以用System.in; 发现System.in是字节流的操作,与Reader(字符流)矛盾,
这时就要用到转换流 InputStreamReader 。为了提高操作效率,使用缓冲技术,选择BufferedReader。 

目的:从 OutputStream,Writer中选择。 因为是文本文件,所以选择Writer。 
设备:硬盘上,一个文件,选择FileWriter。 为了提高操作效率,使用缓冲技术,选择BufferedWriter。 
     
     
  • 示例1:
import java.io.*; 
    class ReadinFile 
        { 
            public static void main(String[] args)throws IOException //这里为了方便阅读,先不做异常处理。 
            { 
                BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in)); 
                BufferedWriter bufw=new BufferedWriter(new FileWriter("readin.txt")); 
                String line=null; 
                while((line=bufr.readLine())!=null) 
                { 
                    if("over".equals(line)) break; 
                    bufw.write(line); 
                    bufw.newLine(); 
                } 
                bufw.close(); 
                bufr.close(); 
            } 
        }
      
      
  • 示例2:
  • import java.io.*;
    public class TestTransForm 
    {
        public static void main(String[] args) throws IOException //这里为了方便阅读,先不做异常处理。 
        {
            InputStreamReader isr = new InputStreamReader(System.in);
            BufferedReader br = new BufferedReader(isr);
            OutputStreamWriter osw = new OutputStreamWriter(
                                     new FileOutputStream("D:\\JavaProject\\demo13\\TransStream\\TransForm.txt",true));
            BufferedWriter bw = new BufferedWriter(osw);
            String str = null;
            str = br.readLine();
            while(str != null)
            {
                if(str.equalsIgnoreCase("exit")) break;
                bw.write(str);
                bw.newLine();
                str = br.readLine();
            }
            br.close();
            bw.close();
        }
    }
           
           
    • 注意:
      (1)构造方法:public FileOutputStream(String name,boolean append) throws FileNotFoundException
      如果append为True,输出字节流就写入文件的末尾,而不是开头(覆盖原来的内容);
      如果append为False,输出字节流就写入文件的开头,即覆盖原来的内容从文件开始处写内容。
      (2)构造方法:public FileOutputStream(String name) throws FileNotFoundException
      每次覆盖原文件的内容,从文件开始处写内容。

    3.5 数据流——数据的存储和数据恢复

    • 数据流:DataInputStream和DataOutputStream
      (0)DataInputStream和DataOutputStream是面向字节的,因此要使用InputStream和OutputStream。
      (1)DataInputStream和DataOutputStream分别继承InputStream和OutputStream,
      它们属于处理流,需要分别“套接”在InputStream和OutputStream类型的节点流上。
      (2)DataInputStream和DataOutputStream提供了可以存取与机器无关的Java原始类数据(如:int,double等)的方法。
      (3)DataInputStream和DataOutputStream的构造方法:
         DataInputStream(InputStream in)
         DataOutputStream(OutputStream out
            
            
    • 示例1:
    • import java.io.*;
      public class TestDataStream
      {
          public static void main(String[] args) throws IOException
          {
              FileOutputStream fout = new FileOutputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt",true);
              BufferedOutputStream bout = new BufferedOutputStream(fout);
              DataOutputStream dout = new DataOutputStream(bout);
              /*DataOutputStream,BufferedOutputStream,FileOutputStream这里使用了流栈。*/
      
              dout.writeInt(110);
              dout.writeUTF("hello,中国");
              dout.writeFloat(3.14f);
              dout.writeChar(97);/*97对应的是'a'*/
              dout.close();/*如果正在使用一个流栈,程序关闭最上面的一个流也就自动的关闭了栈中的所有底层流。*/
      
              FileInputStream fin = new FileInputStream("D:/JavaProject/demo13_IO/DataStream/demo.txt");
              BufferedInputStream bin = new BufferedInputStream(fin);
              DataInputStream din = new DataInputStream(bin);
      
              int i = din.readInt();
              String str = din.readUTF();
              float f = din.readFloat();
              char c = din.readChar();
              fin.close();/*如果正在使用一个流栈,程序关闭最上面的一个流也就自动的关闭了栈中的所有底层流。*/
              System.out.println("int:"+i+"\nString:"+str+"\nfloat:"+f+"\nchar:"+c);
          }
      
      }
               
               
      • 编译,运行:
      • D:\JavaProject\demo13_IO\DataStream>javac TestDataStream.java
        
        D:\JavaProject\demo13_IO\DataStream>java TestDataStream
        int:110
        String:hello,中国
        float:3.14
        char:a
                  
                  
        • 注意:
        •         int i = din.readInt();
                  String str = din.readUTF();
                  float f = din.readFloat();
                  char c = din.readChar();
                  /*此段代码的顺序不能乱,要保证先写入的先读出来的原则,否则会出现错误。
                  *    因此,我们在写代码的时候,我们必须:
                  *         要么为文件中的数据采用固定的格式;
                  *         要么将额外的信息保存到文件中,以便能够对其进行解析以确定数据的寻访位置。
                  */
                     
                     
          [原文链接](https://blog.youkuaiyun.com/jingzi123456789/article/details/72123937)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值