• 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. }  
  • 相关阅读:
    yii 引入文件
    CodeForces 621C Wet Shark and Flowers
    面试题题解
    POJ 2251 Dungeon Master
    HDU 5935 Car(模拟)
    HDU 5938 Four Operations(暴力枚举)
    CodeForces 722C Destroying Array(并查集)
    HDU 5547 Sudoku(dfs)
    HDU 5583 Kingdom of Black and White(模拟)
    HDU 5512 Pagodas(等差数列)
  • 原文地址:https://www.cnblogs.com/huajiezh/p/5263833.html
Copyright © 2020-2023  润新知