詳解JAVA I/O

剛開始學Java時候,一直搞不懂Java裏面的io關係,在網上找了很多大多都是給個結構圖草草描述也看的不是很懂。而且沒有結合到java7 的最新技術,所以自己結合API來整理一下,有錯的話請指正,也希望大家提出寶貴意見。

首先看個圖:(如果你也是初學者,我相信你看了真個人都不好了,想想java設計者真是煞費苦心啊!)

Java I/O系統的類實在是太多了,這裏我們只學習一些基本的和常用的,相信能夠掌握這些就可以解決我們以後的普通應用了

 什麼是數據流(字節流)                                                                                                                                                                      

數據流是指所有的數據通信通道;

有兩類流,InputStream and OutputStream。

Java中每一種流的基本功能依賴於它們InputStream 用於read,OutputStream 用於write, 讀和寫都是相對與內存說的,讀就是從其他地方把數據拿進內存,寫就是把數據從內存推出去
這兩個都是抽象類,不能直接使用

InputStream 的方法有:                                                                                                                             

1.read() :從流中讀入數據 有3中方式:
2.int read(): 一次讀一個字節
3.int read(byte[]) :讀多個字節到數組中
4.int read(byte[],int off,int len) :指定從數組的哪裏開始,讀多長
5.skip() :跳過流中若干字節
6.available() :返回流中可用字節數,但基於網絡時無效,返回0
7.markSupported(): 判斷是否支持標記與復位操作
8.mark() :在流中標記一個位置,要與markSupported()連用
9.reset() :返回標記過的位置
10.close() :關閉流

OutputStream 的方法:                                                                                                                               

1.write(int) :寫一個字節到流中
2.write(byte[]): 將數組中的內容寫到流中
3.write(byte[],int off,int len): 將數組中從off指定的位置開始len長度的數據寫到流中
4.close() :關閉流
5.flush() :將緩衝區中的數據強制輸出

File 類                                                                                                                                                      

File 可以表示文件也可以表示目錄,File 類控制所有硬盤操作
構造器:
1.File(File parent,String child): 用父類和文件名構造
2.File(String pathname) :用絕對路徑構造
3.File(String parent,String child): 用父目錄和文件名構造
4.File(URI uri) :用遠程文件構造
常用方法:

-----------------------------------------------------------------------------------------------------------------------------------------------------------

1.boolean createNewFile();

2.boolean exists();

例子:
//建立 test.txt 文件對象,判斷是否存在,不存在就創建
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2.   
  3. public class CreateNewFile{  
  4.     public static void main(String args[]){  
  5.       File f=new File("test.txt");  
  6.       try{  
  7.          if(!f.exists())  
  8.             f.createNewFile();  
  9.          else  
  10.            System.out.println("exists");  
  11.         }catch(Exception e){  
  12.          e.printStackTrace();  
  13.         }  
  14.     }  
  15. }  

---------------------------------------------------------------------------------------------------------------------------------------------------------

3.boolean mkdir()/mkdirs()

4.boolean renameTo(File destination)
例子://看一下這 mkdir()/mkdirs() 的區別和 renameTo 的用法
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class CreateDir{  
  3.     public static void main(String args[]){  
  4.        File f=new File("test.txt");  
  5.        File f1=new File("Dir");  
  6.        File f2=new File("Top/Bottom");  
  7.        File f3=new File("newTest.txt");  
  8.        try{  
  9.          f.renameTo(f3);  
  10.           f1.mkdir();  
  11.           f2.mkdirs();  
  12.        }catch(Exception e){  
  13.          e.printStackTrace();  
  14.        }  
  15.     }  
  16. }  

--------------------------------------------------------------------------------------------------------------------------------------------------------------

String getPath()/getAbsolutePath()

String getParent()/getName()

例子://硬盤上並沒有parent 目錄和 test.txt 文件,但我們仍然可以操作,因爲我們創建了他們的對象,是對對象進行操

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class Test{  
  3.     public static void main(String args[]){  
  4.         File f=new File("parent/test.txt");  
  5.         File f1=new File("newTest.txt");  
  6.         try{  
  7.            System.out.println(f.getParent());  
  8.            System.out.println(f.getName());  
  9.            System.out.println(f1.getPath());  
  10.            System.out.println(f1.getAbsolutePath());  
  11.           }catch(Exception e){  
  12.              e.printStackTrace();  
  13.           }  
  14.       }  
  15. }  
----------------------------------------------------------------------------------------------------------------------------------------------------------

String list[] //顯示目錄下所有文件
long lastModified() //返回 1970.1.1 到最後修改時間的秒數
boolean isDirectory()
例子://列出目錄下的所有文件和目錄,最後修改時間,是目錄的後面標出<DIR>,是文件的後面標出文件長度

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. import java.util.*;  
  3. public class Dir{  
  4.      public static void main(String args[]){  
  5.           File f=new File("Dir");  
  6.           String[] listAll=null;  
  7.           File temp=null;  
  8.           try{  
  9.               listAll=f.list();  
  10.               for(int i=0;i<listAll.length;i++){  
  11.                    temp=new File(listAll<i>);  
  12.                    System.out.print(listAll<i>+"\t");  
  13.                    if(temp.isDirectory())  
  14.                          System.out.print("\t<DIR>\t");  
  15.                    else  
  16.                      System.out.print(temp.length()+"\t");  
  17.                      System.out.println(new Date(temp.lastModified()))  
  18.            }  
  19.          }catch(Exception e){  
  20.              e.printStackTrace();  
  21.         }  
  22.     }  
  23. }  
文件流的建立                                                                                                                                                                               
File f=new File("temp.txt");
FileInputStream in=new FileInputStream(f);
FileOutputStream out=new FileOutputStream(f);
例子:文件拷貝
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class Copy{  
  3. public static void main(String args[]){  
  4.      FileInputStream fis=null;  
  5.      FileOutputStream fos=null;  
  6.      try{  
  7.         fis=new FileInputStream("c2.gif");  
  8.         fos=new FileOutputStream("c2_copy.gif");  
  9.         int c;  
  10.         while((c=fis.read()) != -1)  
  11.             fos.write(c);  
  12.         }catch(Exception e){  
  13.             e.printStackTrace();  
  14.         }finally{  
  15.             if(fis != nulltry{ fis.close(); }catch(Exception e){ e.printStackTrace(); }  
  16.             if(fos!= nulltry{ fos.close(); }catch(Exception e){ e.printStackTrace(); }  
  17.         }  
  18.     }  
  19. }  
  20.   
  21. <span style="background-color: rgb(0, 102, 0);"><span style="color:#FFFFFF;"><strong>  
  22. </strong></span></span>  
緩衝區流                                                                                                                                                                                             
BufferedInputStream
BufferedOutputStream
他們是在普通文件流上加了緩衝的功能,所以構造他們時要先構造普通流
例子:文件拷貝的緩衝改進
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class Copy{  
  3.    public static void main(String args[]){  
  4.          BufferedInputStream bis=null;  
  5.          BufferedOutputStream bos=null;  
  6.          byte buf[]=new byte[100];  
  7.          try{  
  8.              bis=new BufferedInputStream(new FileInputStream("persia.mp3"));  
  9.              bos=new BufferedOutputStream(new FileOutputStream("persia_copy.mp3"));  
  10.              int len=0;  
  11.              whiletrue ){  
  12.                    len=bis.read(buf);  
  13.                    if(len<=0break;  
  14.                    bos.write(buf,0,len);  
  15.              }  
  16.              bos.flush();//緩衝區只有滿時纔會將數據輸出到輸出流,用flush()將未滿的緩衝區中數據強制輸出  
  17.           }catch(Exception e){  
  18.              e.printStackTrace();  
  19.           }finally{  
  20.              if(bis != nulltry{ bis.close(); }catch(Exception e){ e.printStackTrace(); }  
  21.              if(bos!= nulltry{ bos.close(); }catch(Exception e){ e.printStackTrace(); }  
  22.          }  
  23.     }  
  24. }  

原始數據流                                                                                                                                        

DataInputStream
DataOutputStream
他們是在普通流上加了讀寫原始型數據的功能,所以構造他們時要先構造普通流
方法:
readBoolean()/writeBoolean()
readByte()/writeByte()
readChar()/writeByte()
......
例子://這個流比較簡單,要注意的就是讀時的順序要和寫時的一樣

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class DataOut{  
  3.      public static void main(String args[]){  
  4.      DataOutputStream dos=null;  
  5.      try{  
  6.          dos=new DataOutputStream(new FileOutputStream("dataout.txt"));  
  7.          dos.writeInt(1);  
  8.          dos.writeBoolean(true);  
  9.          dos.writeLong(100L);  
  10.          dos.writeChar('a');  
  11.       }catch(Exception e){  
  12.          e.printStackTrace();  
  13.       }finally{  
  14.          if(dos!=null)  
  15.          try{  
  16.             dos.close();  
  17.          }catch(Exception e){  
  18.       }  
  19.     }  
  20.   }  
  21. }  
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class DataIn{  
  3.      public static void main(String args[]){  
  4.      DataInputStream dis=null;  
  5.      try{  
  6.         dis=new DataInputStream(new FileInputStream("dataout.txt"));  
  7.         System.out.println(dis.readInt());  
  8.         System.out.println(dis.readBoolean());  
  9.         System.out.println(dis.readLong());  
  10.         System.out.println(dis.readChar());  
  11.       }catch(Exception e){  
  12.         e.printStackTrace();  
  13.       }finally{  
  14.          if(dis!=null)  
  15.         try{  
  16.            dis.close();  
  17.         }catch(Exception e){  
  18.       }  
  19.     }  
  20.   }  
  21. }  
對象流                                                                                                                                                                                             

串行化:對象通過寫出描述自己狀態的數值來記述自己的過程叫串行話
對象流:能夠輸入輸出對象的流
將串行化的對象通過對象流寫入文件或傳送到其他地方
對象流是在普通流上加了傳輸對象的功能,所以構造對象流時要先構造普通文件流
注意:只有實現了Serializable接口的類才能被串行化
例子:

[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. class Student implements Serializable{  
  3.     private String name;  
  4.     private int age;  
  5.   
  6.     public Student(String name,int age){  
  7.          this.name=name;  
  8.          this.age=age;  
  9.      }  
  10.   
  11.      public void greeting(){  
  12.           System.out.println("hello ,my name is "+name);  
  13.      }  
  14.   
  15.      public String toString(){  
  16.           return "Student["+name+","+age+"]";  
  17.    }  
  18. }  
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. public class ObjectOutTest{  
  2.       public static void main(String args[]){  
  3.       ObjectOutputStream oos=null;  
  4.       try{  
  5.          oos=new ObjectOutputStream(new FileOutputStream("student.txt"));  
  6.          Student s1=new Student("Jerry",24);  
  7.          Student s2=new Student("Andy",33);  
  8.   
  9.          oos.writeObject(s1);  
  10.          oos.writeObject(s2);  
  11.         }catch(Exception e){  
  12.              e.printStackTrace();  
  13.         }finally{  
  14.              if(oos!=null)  
  15.              try{  
  16.                 oos.close();  
  17.               }catch(Exception e){  
  18.                    e.printStackTrace();  
  19.              }  
  20.           }  
  21.      }  
  22. }  
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class ObjectInTest{  
  3.        public static void main(String args[]){  
  4.        ObjectInputStream ois=null;  
  5.        Student s=null;  
  6.        try{  
  7.          ois=new ObjectInputStream(  
  8.          new FileInputStream("student.txt"));  
  9.          System.out.println("--------------------");  
  10.          s=(Student)ois.readObject();  
  11.          System.out.println(s);  
  12.          s.greeting();  
  13.          System.out.println("--------------------");  
  14.          s=(Student)ois.readObject();  
  15.          System.out.println(s);  
  16.          s.greeting();  
  17.         }catch(Exception e){  
  18.             e.printStackTrace();  
  19.         }finally{  
  20.             if(ois!=null)  
  21.             try{  
  22.               ois.close();  
  23.             }catch(Exception e){  
  24.              e.printStackTrace();  
  25.           }  
  26.        }  
  27.     }  
  28. }  
字符流 InputStreamReader/OutputStreamWriter                                                                                                                                  
上面的幾種流的單位是 byte,所以叫做字節流,寫入文件的都是二進制字節,我們無法直接看,下面要學習的是字節流
Java採用 Unicode 字符集,每個字符和漢字都採用2個字節進行編碼,ASCII 碼是 Unicode 編碼的自集
InputStreamReader 是 字節流 到 字符橋的橋樑 ( byte->char 讀取字節然後用特定字符集編碼成字符)
OutputStreamWriter是 字符流 到 字節流的橋樑 ( char->byte )
他們是在字節流的基礎上加了橋樑作用,所以構造他們時要先構造普通文件流
我們常用的是:
BufferedReader 方法:readLine()
PrintWriter 方法:println()

例子:
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class PrintWriterTest{  
  3.      public static void main(String args[]){  
  4.      PrintWriter pw=null;  
  5.      try{  
  6.         pw=new PrintWriter(new OutputStreamWriter(new FileOutputStream("bufferedwriter.txt")));  
  7.         pw.println("hello world");  
  8.       }catch(Exception e){  
  9.         e.printStackTrace();  
  10.       }finally{  
  11.         if(pw!=null)  
  12.              try{  
  13.                 pw.close();  
  14.                }catch(Exception e){  
  15.                   e.printStackTrace();  
  16.            }  
  17.        }  
  18.    }  
  19. }  
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class BufferedReaderTest{  
  3.          public static void main(String args[]){  
  4.          BufferedReader br=null;  
  5.         try{  
  6.            br=new BufferedReader(new InputStreamReader(new FileInputStream("bufferedwriter.txt")));  
  7.            System.out.println(br.readLine());  
  8.           }catch(Exception e){  
  9.               e.printStackTrace();  
  10.          }finally{  
  11.            if(br!=null)  
  12.              try{  
  13.                 br.close();  
  14.              }catch(Exception e){  
  15.                 e.printStackTrace();  
  16.             }  
  17.         }  
  18.     }  
  19. }  
隨機存取文件 RandomAccessFile                                                                                                                                                       
可同時完成讀寫操作
支持隨機文件操作的方法:
readXXX()/writeXXX()
seek() 將指針調到所需位置
getFilePointer() 返回指針當前位置
length() 返回文件長度
例子:把若干個32位的整數寫到一個名爲 “temp.txt”的文件中,然後利用seek方法,以相反的順序再讀取這些數據
[java] view plain copy
 
 在CODE上查看代碼片派生到我的代碼片
  1. import java.io.*;  
  2. public class RandomFile{  
  3.    public static void main(String args[]){  
  4.         RandomAccessFile raf=null;  
  5.         int data[]={12,31,56,23,27,1,43,65,4,99};  
  6.         try{  
  7.            raf=new RandomAccessFile("temp.txt","rw");  
  8.            for(int i=0;i<data.length;i++)  
  9.                 raf.writeInt(data<i>);  
  10.                 for(int i=data.length-1;i>=0;i--){  
  11.                      raf.seek(i*4);  
  12.                      System.out.println(raf.readInt());  
  13.                 }  
  14.            }catch(Exception e){  
  15.                e.getMessage();  
  16.            }finally{  
  17.                if(raf!=null)  
  18.                try{  
  19.                   raf.close();  
  20.               }catch(Exception e){  
  21.                  e.getMessage();  
  22.             }  
  23.        }  
  24.    }  
  25. }   
小結                                                                                                                                                                                                  

這部分的難點就是類比較複雜,尤其是每個類的構造方式,我認爲記住下面這個圖比記類的繼承關係更好些

字節流:

InputStream
|-- FileInputStream (基本文件流)
|-- BufferedInputStream
|-- DataInputStream
|-- ObjectInputStream
OutputStream 同上圖
BufferedInputStream DataInputStream ObjectInputStream 只是在 FileInputStream 上增添了相應的功能,構造時先構造FileInputStream

 字符流:
Reader
|-- InputStreamReader (byte->char 橋樑)
|-- BufferedReader (常用)

Writer
|-- OutputStreamWriter (char->byte 橋樑)
|-- BufferedWriter
|-- PrintWriter (常用)

 隨機存取文件 RandomAccessFile

發佈了28 篇原創文章 · 獲贊 171 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章