详述JAVA IO流

一、流的概念
       流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设备、外部文件等。
       一个流,必有源端和目的端,它们可以是计算机内存的某些区域,也可以是磁盘文件,甚至可以是Internet上的某个URL。
        流的方向是重要的,根据流的方向,流可分为两类:输入流和输出流。用户可以从输入流中读取信息,但不能写它。相反,对输出流,只能往输入流写,而不能读它。
       实际上,流的源端和目的端可简单地看成是字节的生产者和消费者,对输入流,可不必关心它的源端是什么,只要简单地从流中读数据,而对输出流,也可不知道它的目的端,只是简单地往流中写数据。
       形象的比喻——水流 ,文件======程序 ,文件和程序之间连接一个管道,水流就在之间形成了,自然也就出现了方向:可以流进,也可以流出.便于理解,这么定义流: 流就是一个管道里面有流水,这个管道连接了文件和程序。
 
"IO"对程序语言的设计者来说是一项难度极高的任务.编程思想中这样说过,可见要把IO彻底搞清楚并非简单之事.我也苦心研究过IO但是还不能完全理解.只是理解了主要的一些功能.File类的名字极具的富有欺骗性,刚看或许会认为是一个关于文件的类,但它不是.可以用它来表示某个文件的名字,也可以用它来表示目录里的一组文件的名字.如果它表示的是一组文件,那么你还可以用list()方法来进行查询,它返回String数组.File类的功能不仅限于显示文件或者目录.还可以帮你创建心的目录甚至是目录路径.此外还可以用来检查文件的属性,判断文件是否存在,删除文件等等N多功能.个人觉的IO流是J2SE的核心技术之一,虽然J2EE的程序员精通于它,但是掌握基本的流操作和原理也是很有必要的.说了半天什么是"流"呢?所谓"流"就是一种能生成或接受数据的,代表数据的源和目标的对象,流把I/O设备内部的具体操作封装了起来.JDK文档上说到JAVA的I/O类库分成输入和输出两大部分也就是通常说的读和写.所有的InputStream和Reader的派生类都有一个基本的继承来的能读取单个或者byte数组的read()方法.反之所有的OutputStream和Writer的派生类都有一个基本的能写入单个或byte数组的write()方法.
InputStream的任务就是代表那些从各种输入源获取数据的类,这些源主要有byte数组,String对象,文件,管道,流序列,Internet.这些数据源各自都有与之相对应的InputStream的子类.
1)ByteArrayInputStream:以缓冲区内存为InputStream
2)StringBufferInputStream:以String为InputStream
3)FileInputStream:专门用来读文件
4)PipedInputStream:从PipedOutputStream提取数据实现"管道"功能
5)SequenceInputStream:把两个或者多个InputStream合并成一个.
6)FilterInputStream:一个为decorator定义接口用的抽象类.
OutputStream是解决往哪里输出的类,是byte数组,文件或者是管道.
1)ByteArrayOutputStream:在内存里创建一个缓冲区,数据送到流里就是写入这个缓冲区.
2)FileOutputStream:把数据写入文件.
3)PipedOutputStream:写入这个流的数据,最终都会变成与之相关联的PipedInputStream的数据源.
4)FilterOutputStream:一个能decorator提供接口的抽象类.
自从java1.1对最底层的I/O流类库作了重大修改之后,我们看到了Reader和Writer,这个时候我们也许会想reader和writer是不是要取代InputStream和OutputStream呢?不过事实并非如此,虽然InputStream和OutputStream的部分功能已经被淘汰(你继续用编译会有异常),但是仍然有很多东西是有价值的,它们是面向byte的I/O流,也就是字节流.而Reader和Writer则提供的是Unicode的兼容,也就是字符类.Reader和Writer(我称为读流和写流)我觉的主要的用途在与国际化问题.而原来的I/O类库只支持8位的字节,也就是输入输出流,因为不能很好的处理16位的unicode字符.这里说一个概念就是"标准I/O"是Unix的概念,它的意思是一个程序使用一个信息流.所有输入都是从"标准输入"流进来的,输出都是从"标准输出"出去的.错误的消息有"标准错误"标准I/O的优点是可以很容易的和程序串连起来,并且把一个程序的输出当作另一个程序的输入.新IO是JAVA1.4引入的一个新的I/O类库,位于"java.nio.*"包,这么做只有一个目的就是速度.不过至于这个包中的类我还没具体的使用过HOHO.
JAVA的"对象系列化"能让一个实现了Serializable接口的对象转换成一组byte,这样日后要用这个对象的时候,就可以从byte数据恢复出来,简单的说就是把对象保存在外部文件中.而且这种方法也是跨平台的,你无需考虑自己的对象文件应用于什么平台,这些技术细节虚拟机为我们实现了.序列化一个对象还是比较简单的,只要让它实现Serializable接口就行了(这是一个标记接口(tagging interface)没有方法的接口).但是,当语言引入序列化概念之后,它的很多标准类库的类,包括primitive的wrapper类,所有的容器类,以及别的很多类,都会相应地发生改变.甚至连Class对象都会被序列化.要想序列化对象,你必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream.这时,你就能用writeObject( )方法把对象写入OutputStream了.读的时候,你得把InputStream嵌到ObjectInputStream里面,然后再调用readObject( )方法.不过这样读出来的,只是一个Object的对象.对象序列化的重要用途就是Bean技术和RMI(远程方法调用).
如果想深刻学习掌握JAVA的I/O流,我在这里推荐Elliotte Rusty Harold写的<<Java I/O>>(O’Reilly, 1999)这本书.

二、流的分类
java.io包中的类对应两类流,一类流直接从指定的位置(如磁盘文件或内存区域)读或写,这类流称为结点流(node stream),其它的流则称为过滤器(filters)。过滤器输入流往往是以其它输入流作为它的输入源,经过过滤或处理后再以新的输入流的形式提供给用户,过滤器输出流的原理也类似。

Java的常用输入、输出流
java.io包中的stream类根据它们操作对象的类型是字符还是字节可分为两大类: 字符流和字节流。
 
Java的字节流
InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。
Java的字符流
Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先。
结合开始所说的输入/输出流 ,出现了个一小框架。
                     字节流                         字符流
输入流        InputStream               Reader
输出流        OutputStream            Writer

JAVA字节流

FileInputStream和FileOutputStream
这两个类属于结点流,第一个类的源端和第二个类的目的端都是磁盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。如:

  1. FileInputStream infile = new FileInputStream("myfile.dat");   
  2. FileOutputStream outfile = new FileOutputStream("results.dat");   

要注意的是,构造FileInputStream, 对应的文件必须存在并且是可读的,而构造FileOutputStream时,如输出文件已存在,则必须是可覆盖的。

BufferedInputStream和BufferedOutputStream
它们是过滤器流,其作用是提高输入输出的效率。
DataInputStream和DataOutputStream
这两个类创建的对象分别被称为数据输入流和数据输出流。这是很有用的两个流,它们允许程序按与机器无关的风格读写Java数据。所以比较适合于网络上的数据传输。这两个流也是过滤器流,常以其它流如InputStream或OutputStream作为它们的输入或输出。

Java的字符流

    字符流主要是用来处理字符的。Java采用16位的Unicode来表示字符串和字符,对应的字符流按输入和输出分别称为readers和writers。
InputStreamReader和OutputStreamWriter
在构造这两个类对应的流时,它们会自动进行转换,将平台缺省的编码集编码的字节转换为Unicode字符。对英语环境,其缺省的编码集一般为ISO8859-1。
BufferedReader和BufferedWriter
这两个类对应的流使用了缓冲,能大大提高输入输出的效率。这两个也是过滤器流,常用来对InputStreamReader和OutputStreamWriter进行处理。如:

  1. import java.io.*;   
  2. public class Echo {   
  3.   public static void main(String[] args) {   
  4.     BufferedReader in =   
  5.       new BufferedReader(   
  6.         new InputStreamReader(System.in));   
  7.     String s;   
  8.     try {   
  9.       while((s = in.readLine()).length() != 0)   
  10.         System.out.println(s);   
  11.       // An empty line terminates the program   
  12.     } catch(IOException e) {   
  13.       e.printStackTrace();   
  14.     }   
  15.   }   
  16. }    

该程序接受键盘输入并回显。
对BufferedReader类,该类的readLine()方法能一次从流中读入一行,但对于BufferedWriter类,就没有一次写一行的方法,所以若要向流中一次写一行,可用PrintWriter类将原来的流改造成新的打印流,PrintWriter类有一个方法println(),能一次输出一行。如:

  1. ............   
  2. PrintWriter out = new PrintWriter(new BufferedWriter(   
  3.       new FileWriter("D:/javacode/test.txt")));   
  4. out.println("Hello World!");   
  5. out.close();   
  6. ............  

例子:

1,与控制台相关。的读入/写出。 实现了字符串的复制。

  1. import java.io.*;   
  2. public class TextRead{   
  3.   
  4. public static void main(String[] args){   
  5.    BufferedReader bf = null;/*BufferedReader相当于一个大桶,其实就是内存,这里实现了大量大量的读写 ,而不是读一个字节或字符就直接写如硬盘,加强了对硬盘的保护。*/  
  6.    try{   
  7.     while(true){ // while(true){}循环保证程序不会结束   
  8.        
  9.        bf = new BufferedReader(new InputStreamReader(System.in));   
  10.        /*System.in 为标准输入,System.out为标准输出*/  
  11.        /*InputStreamReader用语将字节流到字符流的转化,这也就是处理流了  
  12.         *在这里相当与2个管道接在System.in与程序之间。  
  13.         *readLine()方法功能比较好用,也就通过处理流来实现更好功能。  
  14.         **/  
  15.      String line = bf.readLine();   
  16.      System.out.println(line);   
  17.     }     
  18.    }catch(Exception e){   
  19.     e.printStackTrace();    
  20.    }finally{    
  21.     //一定要关闭流,用完后。最好放在   
  22.   
  23. filally 里面。     
  24.     try{      
  25.      if(bf!=null){   
  26.       bf.close();   
  27.      }   
  28.     }catch(Exception e){   
  29.        e.printStackTrace();    
  30.     }   
  31.        
  32.    }   
  33.       
  34. }   
  35.   
  36. }   
  37.   

2,与文件 相关的 读写。    实现了文件的复制。

  1. import java.io.*;   
  2. public class TextRead{   
  3.   
  4. public static void main(String[] args){   
  5.    File fin,fout;      
  6.    BufferedReader bf = null;    
  7.    PrintWriter pw = null;   
  8.    try{   
  9.     fin = new File("zzc.txt"); //注意文件与程序都要在同一个文件夹下。zzc.txt为要被复制的文件。   
  10.       
  11.     fout = new File("copyzzc.txt"); //如果没有会自动创建。   
  12.       
  13.     bf = new BufferedReader(new FileReader(fin));   
  14.       
  15.       pw = new PrintWriter(fout); //PrintWriter为打印流,也可以使用BufferedWriter.   
  16.     String line = bf.readLine();   
  17.     while(line!=null){   
  18.      pw.println(line);   
  19.        
  20.      line = bf.readLine();    
  21.     }   
  22.       
  23.       
  24.    }catch(Exception e){   
  25.     e.printStackTrace();   
  26.       
  27.    }finally{   
  28.     try{   
  29.     //关闭 文件。    
  30.      if(bf!=null){   
  31.       bf.close();   
  32.       bf = null;   
  33.      }   
  34.      if(pw!=null){   
  35.       pw.close();   
  36.       pw = null;   
  37.      }   
  38.     }catch(Exception e){   
  39.      e.printStackTrace();    
  40.     }   
  41.    }   
  42.       
  43. }   
  44.   
  45. }   
  46.   

也是在一个百度好友上看到一篇关于流的文章写的更详细,把好多过时的不用的,哪写常用的都分类了,

还有好多类:

像RandomAccessFile类,序列化接口,都十分重要。

Java有一种特殊类型的IO数据流——DataOutputStream——它可以保证“无论数据来自何种机器,只要使用一个DataInputStream收取这些数据,就可用本机正确的格式保存它们.

以后在把示例加上,还有写比较好的方法。

其实感觉这已经是固定模式了,一提到从键盘读取数据 就会联想到:

  1. new BufferedReader(new InputStreamReader(System.in))  

现在水平达不到,还是记些固定格式比较好,以至于会用。

某个老师也说过,创新是建立在扎实的基础之上,越来越觉得基础重要了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值