1. 程式人生 > >黑馬程式設計師:IO流學習

黑馬程式設計師:IO流學習

既然釋放資源對結果沒有影響,那麼,為什要需要釋放資源這個步驟呢?
   原因有二:其一是:讓這個流物件本身是個垃圾,可以被回收,提高效率
     其二是:通過作業系統釋放管現fw.txt檔案的資源

flush()和close()的區別?
   flush():重新整理緩衝區,流物件還可以繼續使用
   close():重新整理緩衝區,關閉流物件。流物件不可以繼續使用



public static void main(String[] args)
{
//建立字元流輸出流物件,這個步驟做了哪些事情?
FileWriter fw=new FileWriter("fw.txt");
/*
  1、建立了fw物件
  2、底層呼叫了作業系統的資源建立了一個fw.txt檔案

  3、把fw物件指向fw.txt檔案
*/
//呼叫物件的寫方法
fw.write("hello,io,我來了");
/*
  字元流物件寫入資料的時候,最小單位是字元
  而資料操作的最基本單位是位元組
  字元=2位元組
  這就是一緩衝區概念,把2個位元組資料放到緩衝區形成一個字元資料 
*/
 //重新整理緩衝區
 fw.flush();
 //釋放資源,關閉之前,會自動去呼叫flush方法
 fw.close();  
在進行字元流或位元組流操作的時候,需要進行異常的處理
}
FileWriter寫入資料的小問題:
1、如何資料的追加寫入?
FileWriter(String fileName,boolean append):
使用帶兩個引數的構造,第二個引數表示是追加寫入

預設是false,就會重頭開始寫入
如果是true,就會追加寫入
2、資料如何換行?
不同的軟體,換行的標準可能不一樣
有些軟體,可以識別常見的換行標識都是可以的
比如說:editplus Eclipse自帶的檔案開啟方式。
在windows中換行是\r\n.而記事本是windows自帶的軟體。所以,它識別的換行只能是\r\n
linux:\n
mac:\r
例 :
public static void main(String[] args)
{
//建立字元輸出流物件
 FileWriter fw=new FileWriter("a.txt");
 //呼叫writer方法
 for(int x=0;x<4;x++)
 {
  fw.write(x+"hello\r\n");

 }
 //釋放資源
 fw.close();
}
--------------------Reader(讀取資料)
   FileReader
   public int read():一次讀取一個字元
 1、字元輸入流物件
 2、呼叫字元輸入流物件的讀取方法,並顯示出來
 3、釋放資源
例:方式一:
public static void main(String[] args) throws IOException
{
//建立字元輸入流物件
FileReader fr=new FileReader("a.txt");
做了幾件事情:
1:建立fr物件
2、找到fw.txt檔案
3、把fw物件指向fw.txt檔案
注意:讀取的時候,檔案一定要存在。不然會報異常:
java.io.FileNotFoundException: fw5.txt (系統找不到指定的檔案。)
/*
//呼叫字元輸入流物件的讀取方法,並顯示出來
int num = fr.read();
System.out.println("num:"+num);
System.out.println("num:"+(char)num);
//我們發現了,read()方法可以自動從頭開始讀取,每次回自動移到下一個位置。
//並且我們發現,程式碼的重複度很高,所以,考慮使用迴圈,但是,問題來了,迴圈的結束條件我不知道
int num4 = fr.read();
System.out.println("num4:"+num4);
System.out.println("num4:"+(char)num4);
//通過測試,我們發現,當沒有資料的時候,我們在讀取的時候,將返回-1
//所以,我們就可以使用-1作為判斷結束條件。
*/
/*
int num = fr.read();
while(num!=-1){
System.out.print((char)num);
num = fr.read(); //再次讀取
}
*/
//開發中改進
int num = 0;
while((num=fr.read())!=-1){
System.out.print((char)num);
}

//釋放資源
fr.close();
例:方式二:
  public static void main(String[] args)
  {
    //建立字元輸入流物件
    FileReader fr=new FileReader("a.txt");
    //呼叫物件的方法 
     //定義一個字元陣列
     char[] chs=new char[1024];//開發中使用
// 讀取資料 定義一個數組,但是這個陣列的大小不好確定。
//char[] chs = new char[4];
//int len = fr.read(chs);
// 重新給len賦值
//System.out.println("***************************");
len = fr.read(chs);
//System.out.println("chs:" + Arrays.toString(chs));
System.out.print(String.copyValueOf(chs));
//System.out.println("len:" + len);
//發現程式碼重複度很高,需要找一個迴圈結束條件。
//意思就是說:當沒有資料的時候,實際讀取長度為-1.所以,len不是陣列的長度,
而是實際讀取資料的長度。
*/
// 讀取資料 定義一個數組,但是這個陣列的大小不好確定。
/*
char[] chs = new char[5];
int len = fr.read(chs);
while(len!=-1){
//chs,0,len的做法對最後一次讀取資料不足有效。
System.out.print(String.copyValueOf(chs,0,len));
len = fr.read(chs);
}
*/
//開發寫法
//陣列的長度定義為多大呢?一般來說是1024的整數倍。
//1T = 1024 G
//1G = 1024 M
//1M = 1024 K
//1K = 1024 byte
//1byte = 8bit
char[] chs = new char[1024]; //2k
int len = 0;
while((len=fr.read(chs))!=-1){
System.out.print(String.copyValueOf(chs,0,len));
}
// 釋放資源
fr.close();
  }
例:
   複製文字檔案:
     思路:
       源文字檔案(D:\\ddd):--讀取資料----檔案用txt開啟是可以看的懂的---字元流----Reader---FileReader
       目標檔案:(F:\\ JJ):---寫入資料---字元流----Writer----FileWriter
       public static void main(String[] args)
       {
          //建立字元輸入流物件
 FileReader fr=new FileReader("d:\\ddd");
 //建立字元輸出流物件
 FileWriter fw=new FileWriter();
 //呼叫物件方法
 //方式一:
 //從資料來源讀取資料
 int num=0;
 while((num=fr.read())!=-1)
 {
   //把資料寫入到文字檔案
   fw.write(num);
 }
 //方式二:
 //定義陣列
 char[] chs=new char[1024];
 int len=0;
 while((len=fr.read(chs))!=-1)
 {
    fw.write(chs,0,len);
 }
       }
------------------------------BufferedWriter
帶緩衝區的輸入輸出流類
  字元緩衝輸入流:BufferedReader
  字元緩衝輸出流:BufferedWriter
BufferedWriter(Writer out)
為什麼要傳入一個Writer 呢?
緩衝區類,只提供緩衝區,不能直接讀寫檔案,需要傳遞一個基本讀寫檔案的物件
喝水:水龍頭有水,你可以把嘴放上去喝。
       不文雅,不方便,不衛生,我就來一個緩衝區,水杯。用水杯接水,然後喝。
假如水杯有了,但是沒有水,有用嗎?
 步驟:
1、建立字元緩衝輸出流物件
2、呼叫該物件的寫方法
3、釋放資源
例:
    需求:往文字檔案寫入一句話
    public static void main(String[] args)
    {
    //建立字元緩衝輸出流物件
    FileWriter fw=new FileWriter("bw.txt"); //真正的讀寫操作
    BufferedWriter bw=new BufferedWriter(fw); //緩衝區類
    //簡化方式
      BufferedWriter bw=new BufferedWriter(new FileWriter("b.txt"));
      //寫資料
      bw.write("hello");
      bw.flush();
      //釋放資源
      bw.close();
      // fw.close(); 因為bw的關閉其實就是fw的關閉
    }
-----------------------------BufferedReader
字元緩衝輸入流讀取資料:
A:一次讀取一個字元
B:一次讀取一個字元陣列
public static void main(String[] args)
{
//建立字元緩衝輸入物件
BufferedReader br=new BufferedReader(new FileReader(bw.txt));
//讀取資料
  方式一:
    int num=0;
    while((num=br.read())!=-1)
    {
    System.out.println((char)num);
    }
    方式二:
     char[] chs=new char[1024];
     int len=0;
     while((len=br.read(chs)!=-1)
     {
System.out.print(String.copyValueOf(chs,0.len));
     }
     br.close();
}
當兩個種方式都寫在程式裡面時,只能使用一種方式。別外一個方式需要註釋掉了
 因當一種方式進行read()操作後,指標已經指到最後一位了。如果在進行另外一種方式進行read操作
 那顯示在控制檯上面的將會什麼都不會顯示
 字元高效緩衝流的特殊方式:
  BufferedReader
public String readLine():根據行結束符讀取一行資料,並把該行資料(不包括結束符)作為一個字串返回
BufferedWriter
public void newLine();寫入一個行分割符,可以識別不同的系統。寫入不同的分割符
例:
public static void main(String[] args)throws IOException
{
 //建立字元緩衝輸出流物件
BufferedWriter bw=new BufferWriter(new FileWriter("bw2.txt"))
//寫入資料
for(int x=0;x<10;x++)
{
bw.write("hello"+x)
bw.newLine();//換行
}
bw.close();
//建立字元緩衝輸入流物件
BufferedrReader br=new BufferedReader(new FileReader("bw2.txt"));
String line=null;
while((line=br.readLine())!=null)
{
System.out.println(line);
}
br.close();
}

複製文字檔案:使用高效流實現
 使用高效流,我有三種方式;
 A:讀取一個字元:read();
 B:讀取一個字元陣列 : read(char[] ch);
 C:讀取一個字串 :  readLine();
思路:
原始檔:“D:\\java”----如果用記事本開啟可以看的懂的就用---字元流---Reader----FileReader----BufferedReader
目標檔案:“G:\\test”--- 字元流-----Writer----FileWriter----BufferedWriter
public static void main(String[] args)
{
  //建立字元輸入流對像(封裝原始檔路徑)
  BufferedReader br=new BufferReader(new FileReader("d:\\java"));
  //建立字元輸出流物件(封裝目標檔案路徑)
  BufferedWriter bw=new BufferWriter(new FileWriter("G:\\test"));
  //讀取資料
     String len=null;
     while((len=br.readLine())!=null)
     {
     //把資料寫入文字檔案中
       bw.write(len);
       bw.newLine(); //換行
       bw.flush(); //重新整理緩衝區
     }
     //釋放資源
     bw.close();
     br.close();
}
從程式 的角度:顯示就用writer 就是輸出流:就像印表機
               儲存就是reader 就是輸入流:就打掃描器
      當要程式進行檔案的複製功能時,那麼原始檔就是Reader()功能,先把已知的件先讀取出來,把
      目標檔案(通過Wtriter()功能)。把原始檔裡面的內容寫進目標檔案中
JDK7的新特性:
 * catch()裡面的異常類,可以用|隔開,也就是說,一個catch可以捕獲多個異常了。
 * 注意:可以使用|隔開的異常是平級的。
 * catch (NullPointerException | ArithmeticException e) {
e.printStackTrace();
}
如果有子父關係,建議使用一個try,多個catch的情況。
如果是平級關係,建議使用JDK7的新特性,就是一個catch可以寫多個異常類名,用|隔開