在java程序中,对于数据的输入/输出操作以“流”(stream)方式进行,jdk提供了各式各样的“流”类,用来获取不同种类的数据;程序中通过标准的方法输入或输出数据
java.io包定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同的角度对其进行分类:

1.按数据流的方向可以分为输入流和输出流;
2.按照处理数据单位不同可以分为字节流和字符流;
3.按照功能不同可以分为节点流和处理流;

jdk所提供的所有流类型位于包java.io内都分别继承自以下四种流类型:

输入/输出
字节流 字符流
输入流 InputStream Reader
输出流 OutpuStream Writer


节点流和处理流:
1.节点流为可以从一个特定的数据源(节点)读写数据(如:文件,内存):

流_第1张图片

2.处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理 为程序提供更为强大的读写功能。

流_第2张图片
流_第3张图片


InputStream:
继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8 bit=1byte)
InputStream的子类:
AudioInputStream,FileInputStream,InputStream, ObjectInputStream,PipedInputStream,SequenceInputStream,
StringBufferInputStream,FilterInputStream的子类(BufferedInputStream, CheckedInputStream, CipherInputStream, DataInputStream, DeflaterInputStream, DigestInputStream, InflaterInputStream, LineNumberInputStream, ProgressMonitorInputStream, PushbackInputStream)
InputStream的基本方法可以参考API,这里不具体介绍了.

OutputStream:
继承自OutputStream的流用于输出数据,且数据单位为字节(8bit)
OutputStream的子类:
ByteArrayOutputStream, FileOutputStream,  ObjectOutputStream, OutputStream, PipedOutputStream,FilterOutputStream的子类(BufferedOutputStream, CheckedOutputStream, CipherOutputStream, DataOutputStream, DeflaterOutputStream, DigestOutputStream, InflaterOutputStream, PrintStream)
OutputStream的基本用法可以参考API.


Reader:
继承自Reader的流都是用于向程序中输入数据,且数据的单位是字符(16bit=2byte)
Reader子类:
BufferedReader的子类(LineNumberReader), CharArrayReader, FilterReader的子类(PushbackReader), InputStreamReader的子类(FileReader), PipedReader, StringReader
Reader基本用法参考API,同上。



Writer:
继承自Writer的流都是用于程序中输入数据,且数据的单位为字符(16bit,2byte)1byte = 8bits(8位)
Writer的子类:
BufferedWriter, CharArrayWriter, FilterWriter, OutputStreamWriter的子类(FileWriter), PipedWriter, PrintWriter, StringWriter
Writer的基本用法参考API,同上。

下面再通过图解直观 InputStream/OutputStream Reader/Writer

1.继承自InputStream/OutputStream的流是用于向程序中输入/输出数据,深色的为节点流,浅色的为处理流。

流_第4张图片
流_第5张图片

2.继承自Reader/Writer的流是用于向程序中输入/输出数据,如图,深色的为节点流,浅色的为处理流。

流_第6张图片



下面简单的介绍下常用的流类型:

缓冲流:
缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率。
jdk提供了四种缓冲流:
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush方法将会使内存中的数据立刻写出


点击(此处)折叠或打开

  1. public class TestFileInputStream {
  2.     
  3.     public static void main(String[] args){
  4.         
  5.         FileOutputStream out = null;
  6.         FileInputStream in = null;
  7.         
  8.     
  9.             try{
  10.             out = new FileOutputStream("B:/Java/src/IO/diy.txt");
  11.             in = new FileInputStream("B:/Java/src/IO/diy.txt");
  12.             out.write(11);
  13.             out.close();
  14.             }catch(IOException e1){
  15.                 
  16.             System.out.println("找不到文件");
  17.             e1.printStackTrace();
  18.             System.exit(-1);
  19.         }
  20.          
  21.         int ss = 0;

  22.         try{
  23.         while((ss = in.read()) != -1){
  24.             
  25.             System.out.println(ss);
  26.       }
  27.     }catch(IOException e2){
  28.         
  29.         e2.printStackTrace();
  30.     }
  31.   }
  32. }


点击(此处)折叠或打开

  1. public class TestFileReader {
  2.    
  3.     public static void main(String[] args){
  4.         
  5.     FileReader re = null;
  6.     FileWriter wr = null;
  7.     
  8.     try{
  9.          wr = new FileWriter("B:/Java/src/diy.txt");
  10.          for(int i =0;i<65535;i++){
  11.             wr.write(i);
  12.          }
  13.         wr.close();
  14.      }catch(IOException e1){
  15.         
  16.         e1.printStackTrace();
  17.         System.exit(-1);
  18.      }
  19.     
  20.     try{
  21.         
  22.         re = new FileReader("B:/Java/src/diy.txt");
  23.  
  24.     }catch(FileNotFoundException e){
  25.         
  26.         System.out.println("文件不存在");
  27.         e.printStackTrace();
  28.         System.exit(-1);
  29.     } 
  30.     
  31.     try{
  32.         int i = 0;
  33.         while((= re.read()) != -1){
  34.             
  35.             System.out.print((char)i);
  36.         }
  37.          re.close();
  38.         }catch(IOException e){
  39.         
  40.            e.printStackTrace();
  41.     }
  42.   }
  43. }



转换流:
InputStreamReader和OutputStreamWriter用于字节数据到字符数据之间的转换
InputStreamReader 需要和InputStream "套接"
OutputStreamWriter需要和OutputStream"套接"


点击(此处)折叠或打开

  1. public class TransStreamWR {
  2.    
  3.     public static void main(String[] args){
  4.     OutputStreamWriter out = null;
  5.     InputStreamReader red = null;
  6.     
  7.     try{
  8.         out = new OutputStreamWriter(new FileOutputStream("B:/Java/src/diy.txt"));
  9.         red =new InputStreamReader(new FileInputStream("B:/Java/src/diy.txt"));

  10.           for(int i = 0;i<65535;i++){
  11.             
  12.              out.write(i);
  13.         }
  14.         
  15.         out.flush();
  16.         out.close();
  17.     }catch(IOException e){
  18.         
  19.         e.printStackTrace();
  20.         System.exit(-1);
  21.      }
  22.     
  23.     try{
  24.         
  25.         int ss = 0;
  26.         while((ss = red.read()) != -1){
  27.       
  28.            System.out.println(ss);
  29.         }
  30.         
  31.         red.close();
  32.     }catch(IOException e){
  33.         
  34.         e.printStackTrace();
  35.         System.exit(-1);

  36.     }  
  37.   }
  38. }
有朋友会问,为什么没有把字符流转换为字节流呢,完全没有这个必要!既然可以一下读取两个字节,为什么要换成读取一个字节的呢,如果需要读取一个字节,那直接用字节流处理就行了。

数据流:
DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,它属于处理流,需要分别 ”套接“在InputStream和OutputStream类型的节点流上
DataInputStream和DataOutputStream提供了可以存取与机器无关的java原始类型数据(如:int,double等)


点击(此处)折叠或打开

  1. public class TestDataStream {
  2.   
  3.     public static void main(String[] args){
  4.         
  5.         DataOutputStream doo = null;
  6.         DataInputStream di = null;
  7.         ByteArrayOutputStream bar = new ByteArrayOutputStream();
  8.         ByteArrayInputStream bit = null;
  9.      try{
  10.          
  11.          doo = new DataOutputStream(bar);
  12.          doo.writeInt(1);
  13.          doo.writeChar('w');
  14.          doo.writeFloat((float) 33.3);
  15.          doo.writeDouble(1111111111.1111111111111111);
  16.          doo.writeBoolean(false);
  17.          bit = new ByteArrayInputStream(bar.toByteArray());
  18.          doo.flush();
  19.          doo.close();
  20.          bar.close();
  21.      }catch(IOException e){
  22.          
  23.          e.printStackTrace();
  24.          System.exit(-1);
  25.      }
  26.      
  27.      try{
  28.          
  29.          di = new DataInputStream(bit);
  30.          System.out.println(di.readInt());
  31.          System.out.println(di.readChar());
  32.          System.out.println(di.readFloat());
  33.          System.out.println(di.readDouble());
  34.          System.out.println(di.readBoolean()); //一定要按照顺序读取,否则会出现错误答案
  35.      }catch(IOException e){
  36.          
  37.          e.printStackTrace();
  38.          System.exit(-1);
  39.     }
  40.    }
  41.  }



===============================================================================================
Print流:

PrintWriter和PrintStream都属于输出流,分别针对与字符和字节
PrintWriter和PrintStream提供了重载的print
println方法用于多种数据类型的输出
PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检查错误状态获取错误信息
PrintWriter和PrintStream有自动flush功能


点击(此处)折叠或打开

  1. public class TestPrintStream {
  2.     
  3.     public static void main(String[] args){
  4.         
  5.         PrintStream pr = null;
  6.         
  7.         try{
  8.             
  9.             pr = new PrintStream(new FileOutputStream("B:/Java/src/diy.log"));
  10.             
  11.         }catch(IOException e){
  12.             
  13.             e.printStackTrace();
  14.         }

  15.         if(pr != null)
  16.         System.setOut(pr);

  17.         for(int i = 0;i<60000;i++){
  18.             
  19.             System.out.print((char)i);
  20.         }
  21.     }
  22. }



Object流:
直接将Object写入或读出
这其中涉及三个重要的关键字:

transient
serializable
externalizable


点击(此处)折叠或打开

  1. public class S implements Serializable{ //可以被序列化
  2.     
  3.     int i = 32;
  4.     int j = 9;
  5.     transient int m = 11; //隐藏不可见
  6.     
  7. }
如果该类被存放在Object流中,则该类必须实现serializable接口,就是可以被序列化。查看API可以发现,该接口无任何方法和成员变量。
如果成员变量被transient修饰,则在被序列化时,该变量不被存放在流中,流对其不可见。

点击(此处)折叠或打开

  1. public class TestObject{
  2.      
  3.      public static void main(String[] args) throws Exception{
  4.          
  5.          FileInputStream in = null;
  6.          S s = new S();
  7.          s.m = 8;
  8.     
  9.          FileOutputStream fos = new FileOutputStream("B:/Java/src/diy.txt");
  10.             ObjectOutputStream so = new ObjectOutputStream(fos);
  11.              so.writeObject(s);
  12.              so.flush();
  13.              so.close();
  14.             FileInputStream fis = new FileInputStream("B:/Java/src/diy.txt");
  15.             ObjectInputStream ois = new ObjectInputStream(fis);
  16.             try{
  17.             S t = (S)ois.readObject();
  18.             System.out.println(t.+ " " + " " + t.j + " " + t.m);
  19.             }catch(ClassNotFoundException e1){
  20.                 
  21.                 e1.printStackTrace();
  22.             }catch (IOException e2) {
  23.                 
  24.                 e2.printStackTrace();
  25.        }
  26.      }
  27.   }
当一个类要使用externalizable这个接口的时候,自定义序列化,可以发现 externalizable实现了 Serializable 接口,而且有两个成员函数:
void readExternal(ObjectInput in)
The object implements the readExternal method to restore its contents by calling the methods of DataInput for primitive types and readObject for objects, strings and arrays.
void writeExternal(ObjectOutput out)
The object implements the writeExternal method to save its contents by calling the methods of DataOutput for its primitive values or calling the writeObject method of ObjectOutput for objects, strings, and arrays.

上面简单的介绍了java中的流,用于学习总结,如有不当之处,请读者指正!

你可能感兴趣的:(流)