zoukankan      html  css  js  c++  java
  • Java IO详解(转)

    IO是Java及众多编程语言很重要的一块,同时很多程序的瓶颈和耗时操作也都在IO这块。

    一、简介

    IO操作面临很多问题,信息量的巨大,网络的环境等等,因为IO不仅仅是对本地文件、目录的操作,有时对二进制流、还有一部分是网络方面的资源,所以多种原因直接造成IO操作无疑是耗时且复杂多变的。Java对IO的支持是个不断的演变过程,经过了很多的优化,直到JDK1.4以后,才趋于稳定,在JDK1.4中,加入了nio类,解决了很多性能问题,虽然我们有足够的理由不去了解关于Java IO以前的情况,但是为了学好现在的类,我们还是打算去研究下,通过掌握类的优化情况来彻底理解IO的机制!Java IO主要主要在java.io包下,分为四大块近80个类:

    1、基于字节操作的I/O接口:InputStream和OutputStream

    2、基于字符操作的I/O接口:Writer和Reader

    3、基于磁盘操作的I/O接口:File

    4、基于网络操作的I/O接口:Socket(不在java.io包下)

    影响IO性能的无非就是两大因素:数据的格式及存储的方式,前两类主要是数据格式方面的,后两个类是存储方式方面的:本地和网络。所以策划好这两个方面的活动,有助于我们合理使用IO。

    二、基于字节的I/O操作(InputStream和OutputStream)

    我们先来看看类图:

    图1

    图2

    二者类似,我只详细讲解InputStream类,OutputStream留给大家自己去学习。InputStream类是个抽象类,里面核心的方法就是read()、read(byte b[])、read(byte b[], int off, int len),这三个方法是用于读取数据的底层的方法,他们可以用来读取一下这些类型的数据:

    A. 字节数组

    B. String对象

    C. 文件

    D. 管道,从一端进入,从另一端输出

    E. 流

    F. internet资源

    每一种数据源都有相应的InputStream子类,因为InputStream是个处于顶层的类,用来处理各种数据源的类都继承了InputStream类,我们来看看这些类:

    ByteArrayInputStream:处理字节数组的类,允许将内存的缓冲区当做InputStream使用。

    StringBufferInputStream:将String转换成InputStream,内部实现用的是StringBuffer。

    FileInputStream:从文件中读取数据。

    PipedInputStream:用于从管道中读取数据。

    SequenceInputStream:将多个流对象转化成一个InputStream。

    FilterInputStream:装饰器类,为其它InputStream类提供功能。

    做过关于IO操作的读者知道,我们很少单独使用哪个类来实现IO操作,平时都是几个类合起来使用,这其实体现了一种装饰器模式(详见:http://blog.csdn.net/zhangerqing)的思想,在后面的分析中我们会详细的分析。从上面的图1中我们可以看出,FilterInputStream虽说是Inputstream的子类,但它依然是BufferedInputStream、DataInputStream、LineNumberInputStream、PushbackInputStream类的父类,这四个类分别提供了最贴近我们程序员使用的方法,如:readInt() 、readInt()、readInt()等等。对于IO操作,不管是磁盘还是网络,最终都是对字节的操作,而我们平时写的程序都是字符形式的,所以在传输的过程中需要进行转换。在字符到字节的转换过程中,我们需要用到一个类:InputStreamReader。

    三、基于字符的I/O操作(Writer和Reader)

    图3

    图4

    Writer和Reader操作的目的就是操作字符和不是字节,和InputStream和OutputStream配合增加IO效果。通过InputStreamReader和OutputStreamReader可以进行字节和字符的转换,设计Writer和Reader的目的是国际化,使IO操作支持16位的Unicode。我把它们单独的画出来,因为要是全画的话,太大了放不下,有兴趣的TX可以在rational rose中导入其带的JDK类图看看,很过瘾的!

    四、基于磁盘的I/O操作(File)

    五、基于网络的I/O操作(Socket)

    六、NIO

    四-六部分由于时间关系,还没有整理完,后续会补出来!

    七、经典IO操作

    1、缓冲输入文件。

    [java] view plain copy
     
    1. import java.io.BufferedReader;  
    2. import java.io.FileReader;  
    3.   
    4. public class InputStreamTest {  
    5.   
    6.     public static String read(String filename) throws Exception {  
    7.         BufferedReader br = new BufferedReader(new FileReader(filename));  
    8.         String s;  
    9.         StringBuffer sb = new StringBuffer();  
    10.         while ((s = br.readLine()) != null) {  
    11.             sb.append(s + " ");  
    12.         }  
    13.         br.close();  
    14.         return sb.toString();  
    15.     }  
    16.   
    17.     public static void main(String[] args) throws Exception {  
    18.         System.out.println(read("src/InputStreamTest.java"));  
    19.     }  
    20.  }  

    这段代码是从磁盘读入InputStreamTest.java文件,然后转换成字符串。输出就是将源文件原样输出。

    2、从内存中读取。

    [java] view plain copy
     
    1. import java.io.StringReader;  
    2.   
    3. public class MemoryInput {  
    4.   
    5.     public static void main(String[] args) throws Exception {  
    6.         StringReader in = new StringReader(  
    7.                 InputStreamTest.read("src/MemoryInput.java"));  
    8.         int c;  
    9.         while ((c = in.read()) != -1)  
    10.             System.out.println((char) c);  
    11.     }  
    12.   
    13. }  

    read返回的是int类型的数据,所以在输出语句中用char做了强类型转换。该程序将一个一个的输出字符。

    3、基本的文件输出。

    [java] view plain copy
     
    1. import java.io.BufferedReader;  
    2. import java.io.BufferedWriter;  
    3. import java.io.FileWriter;  
    4. import java.io.PrintWriter;  
    5. import java.io.StringReader;  
    6.   
    7. public class BasicFileOutput {  
    8.   
    9.     static String file = "basie.out";  
    10.   
    11.     public static void main(String[] args) throws Exception {  
    12.         BufferedReader in = new BufferedReader(new StringReader(  
    13.                 InputStreamTest.read("src/BasicFileOutput.java")));  
    14.         PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(  
    15.                 file)));  
    16.         int lineCount = 1;  
    17.         String s;  
    18.         while ((s = in.readLine()) != null) {  
    19.             out.println(lineCount++ + ": " + s);  
    20.         }  
    21.         out.close();  
    22.         System.out.println(InputStreamTest.read(file));  
    23.     }  
    24. }  

    输出:

    1: import java.io.BufferedReader;

    2: import java.io.BufferedWriter;

    3: import java.io.FileWriter;

     4、RandomAccessFile

    RandomAccessFile被我们称为”自我独立的类”,因为它独立于我们前面说的IO类,与InputStream和OutputStream没什么关系,除了实现了DataOutput, DataInput两个接口外。所有方法都是重新编写,而且很多都是native方法,我们来看个例子,了解下这个类:

    5、管道流

    八、标准I/O

    就是我们最原始的使用的从控制台输入或者输出的那些类和方法,如System.in、System.out等。

    [java] view plain copy
     
    1. public class StandardIO {  
    2.   
    3.     public static void main(String[] args) throws IOException {  
    4.         BufferedReader in = new BufferedReader(new InputStreamReader(System.in));  
    5.         String s;  
    6.         while ((s = in.readLine()) != null && s.length() != 0)  
    7.             System.out.println(s);  
    8.     }  
    9. }  

    System.in返回的是未经包装的InputStream对象,所以需要进行装饰,经InputStreamReader转换为Reader对象,放入BufferedReader的构造方法中。除此之外,System.out和System.err都是直接的PriintStream对象,可直接使用。我们也可以使用java.util包下的Scanner类来代替上述程序:

    [java] view plain copy
     
    1. public class StandardIO {  
    2.   
    3.     public static void main(String[] args) throws IOException {  
    4.         Scanner in = new Scanner(System.in);  
    5.         String s;  
    6.         while((s = in.next()) != null && s.length() != 0){  
    7.             System.out.println(s);  
    8.         }  
    9.     }  
    10. }  

    九、性能分析及总结

    1、一个文件读写工具类。

    [java] view plain copy
     
    1. import java.io.BufferedReader;  
    2. import java.io.File;  
    3. import java.io.FileReader;  
    4. import java.io.IOException;  
    5. import java.io.PrintWriter;  
    6. import java.util.ArrayList;  
    7. import java.util.Arrays;  
    8.   
    9. /** 
    10.  * 一个非常实用的文件操作类 . 2012-12-19 
    11.  *  
    12.  * @author Bruce Eckel , edited by erqing 
    13.  *  
    14.  */  
    15. public class TextFile extends ArrayList<String> {  
    16.   
    17.     private static final long serialVersionUID = -1942855619975438512L;  
    18.   
    19.     // Read a file as a String  
    20.     public static String read(String filename) {  
    21.         StringBuilder sb = new StringBuilder();  
    22.         try {  
    23.             BufferedReader in = new BufferedReader(new FileReader(new File(  
    24.                     filename).getAbsoluteFile()));  
    25.             String s;  
    26.             try {  
    27.                 while ((s = in.readLine()) != null) {  
    28.                     sb.append(s);  
    29.                     sb.append(" ");  
    30.                 }  
    31.             } finally {  
    32.                 in.close();  
    33.             }  
    34.   
    35.         } catch (IOException e) {  
    36.             throw new RuntimeException(e);  
    37.         }  
    38.         return sb.toString();  
    39.     }  
    40.   
    41.     // Write a single file in one method call  
    42.     public static void write(String fileName, String text) {  
    43.         try {  
    44.             PrintWriter out = new PrintWriter(  
    45.                     new File(fileName).getAbsoluteFile());  
    46.             try {  
    47.                 out.print(text);  
    48.             } finally {  
    49.                 out.close();  
    50.             }  
    51.         } catch (IOException e) {  
    52.             throw new RuntimeException(e);  
    53.         }  
    54.     }  
    55.   
    56.     // Read a file,spilt by any regular expression  
    57.     public TextFile(String fileName, String splitter) {  
    58.         super(Arrays.asList(read(fileName).split(splitter)));  
    59.         if (get(0).equals(""))  
    60.             remove(0);  
    61.     }  
    62.   
    63.     // Normally read by lines  
    64.     public TextFile(String fileName) {  
    65.         this(fileName, " ");  
    66.     }  
    67.   
    68.     public void write(String fileName) {  
    69.         try {  
    70.             PrintWriter out = new PrintWriter(  
    71.                     new File(fileName).getAbsoluteFile());  
    72.             try {  
    73.                 for (String item : this)  
    74.                     out.println(item);  
    75.             } finally {  
    76.                 out.close();  
    77.             }  
    78.   
    79.         } catch (IOException e) {  
    80.             throw new RuntimeException(e);  
    81.         }  
    82.   
    83.     }  
    84.   
    85.     // test,I have generated a file named data.d at the root  
    86.     public static void main(String[] args) {  
    87.   
    88.         /* read() test */  
    89.         System.out.println(read("data.d")); // testing is OK!  
    90.   
    91.         /* write() test */  
    92.         write("out.d", "helloworld egg"); // testing is OK!  
    93.   
    94.         /* constractor test */  
    95.         TextFile tf = new TextFile("data.d"); // testing is OK!  
    96.   
    97.     }  
    98.   
    99. }  

    2、读取二进制文件。

    [java] view plain copy
     
    1. import java.io.BufferedInputStream;  
    2. import java.io.File;  
    3. import java.io.FileInputStream;  
    4. import java.io.IOException;  
    5.   
    6. /** 
    7.  * to read the binary file 
    8.  *  
    9.  * @author erqing 
    10.  *  
    11.  */  
    12. public class BinaryFile {  
    13.   
    14.     /* the parametre is a file */  
    15.     public static byte[] read(File file) throws IOException {  
    16.         BufferedInputStream bf = new BufferedInputStream(new FileInputStream(  
    17.                 file));  
    18.         try {  
    19.             byte[] data = new byte[bf.available()];  
    20.             bf.read(data);  
    21.             return data;  
    22.         } finally {  
    23.             bf.close();  
    24.         }  
    25.     }  
    26.   
    27.     /* the param is the path of a file */  
    28.     public static byte[] read(String file) throws IOException {  
    29.         return read(new File(file).getAbsoluteFile());  
    30.     }  
    31. }  
  • 相关阅读:
    26个Jquery使用小技巧
    jQuery之浮动窗口
    Visual Studio 2010 TFS指南
    Python
    HTML5小菜
    记一次重构经历【转载】
    Python学习笔记
    Spring.Net+NHibenate+Asp.Net mvc +ExtJs 系列
    搜索分词实现
    UML概要
  • 原文地址:https://www.cnblogs.com/huajiezh/p/5263833.html
Copyright © 2011-2022 走看看