java-關於文件操作-輸出流的使用


11.3.1.3 讀取文件

         雖然前面介紹了流的概念,但是這個概念對於初學者來說,還是比較抽象的,下面以實際的讀取文件為例子,介紹流的概念,以及輸入流的基本使用。

         按照前面介紹的知識,將文件中的數據讀入程序,是將程序外部的數據傳入程序中,應該使用輸入流——InputStream或Reader。而由於讀取的是特定的數據源——文件,則可以使用輸入對應的子類FileInputStream或FileReader實現。

         在實際書寫代碼時,需要首先熟悉讀取文件在程序中實現的過程。在Java語言的IO編程中,讀取文件是分兩個步驟:1、將文件中的數據轉換為流,2、讀取流內部的數據。其中第一個步驟由系統完成,只需要創建對應的流對象即可,對象創建完成以后步驟1就完成了,第二個步驟使用輸入流對象中的read方法即可實現了。

         使用輸入流進行編程時,代碼一般分為3個部分:1、創建流對象,2、讀取流對象內部的數據,3、關閉流對象。下面以讀取文件的代碼示例:

                   import java.io.*;

/**

 * 使用FileInputStream讀取文件

 */

public class ReadFile1 {

         public static void main(String[] args) {

                   //聲明流對象

                   FileInputStream fis = null;                 

                   try{

                            //創建流對象

                            fis = new FileInputStream("e:\\a.txt");

                            //讀取數據,並將讀取到的數據存儲到數組中

                            byte[] data = new byte[1024]; //數據存儲的數組

                            int i = 0; //當前下標

                            //讀取流中的第一個字節數據

                            int n = fis.read();

                            //依次讀取后續的數據

                            while(n != -1){ //未到達流的末尾

                                     //將有效數據存儲到數組中

                                     data[i] = (byte)n;

                                     //下標增加

                                     i++;

                                     //讀取下一個字節的數據

                                      n = fis.read();

                            }

                           

                            //解析數據

                            String s = new String(data,0,i);

                            //輸出字符串

                            System.out.println(s);

                   }catch(Exception e){

                            e.printStackTrace();

                   }finally{

                            try{

                                     //關閉流,釋放資源

                                     fis.close();

                            }catch(Exception e){}

                   }

         }

}

         在該示例代碼中,首先創建一個FileInputStream類型的對象fis:

                   fis = new FileInputStream("e:\\a.txt");

         這樣建立了一個連接到數據源e:\a.txt的流,並將該數據源中的數據轉換為流對象fis,以后程序讀取數據源中的數據,只需要從流對象fis中讀取即可。

         讀取流fis中的數據,需要使用read方法,該方法是從InputStream類中繼承過來的方法,該方法的作用是每次讀取流中的一個字節,如果需要讀取流中的所有數據,需要使用循環讀取,當到達流的末尾時,read方法的返回值是-1。

         在該示例中,首先讀取流中的第一個字節:

                   int n = fis.read();

         並將讀取的值賦值給int值n,如果流fis為空,則n的值是-1,否則n中的最后一個字節包含的時流fis中的第一個字節,該字節被讀取以后,將被從流fis中刪除。

         然后循環讀取流中的其它數據,如果讀取到的數據不是-1,則將已經讀取到的數據n強制轉換為byte,即取n中的有效數據——最后一個字節,並存儲到數組data中,然后調用流對象fis中的read方法繼續讀取流中的下一個字節的數據。一直這樣循環下去,直到讀取到的數據是-1,也就是讀取到流的末尾則循環結束。

         這里的數組長度是1024,所以要求流中的數據長度不能超過1024,所以該示例代碼在這里具有一定的局限性。如果流的數據個數比較多,則可以將1024擴大到合適的個數即可。

         經過上面的循環以后,就可以將流中的數據依次存儲到data數組中,存儲到data數組中有效數據的個數是i個,即循環次數。

         其實截至到這里,IO操作中的讀取數據已經完成,然后再按照數據源中的數據格式,這里是文件的格式,解析讀取出的byte數組即可。

         該示例代碼中的解析,只是將從流對象中讀取到的有效的數據,也就是data數組中的前n個數據,轉換為字符串,然后進行輸出。

         在該示例代碼中,只是在catch語句中輸出異常的信息,便於代碼的調試,在實際的程序中,需要根據情況進行一定的邏輯處理,例如給出提示信息等。

         最后在finally語句塊中,關閉流對象fis,釋放流對象占用的資源,關閉數據源,實現流操作的結束工作。

         上面詳細介紹了讀取文件的過程,其實在實際讀取流數據時,還可以使用其它的read方法,下面的示例代碼是使用另外一個read方法實現讀取的代碼:

                   import java.io.FileInputStream;

/**

 * 使用FileInputStream讀取文件

 */

public class ReadFile2 {

         public static void main(String[] args) {

                   //聲明流對象

                   FileInputStream fis = null;                 

                   try{

                            //創建流對象

                            fis = new FileInputStream("e:\\a.txt");

                            //讀取數據,並將讀取到的數據存儲到數組中

                            byte[] data = new byte[1024]; //數據存儲的數組

                            int i = fis.read(data);

                           

                            //解析數據

                            String s = new String(data,0,i);

                            //輸出字符串

                            System.out.println(s);

                   }catch(Exception e){

                            e.printStackTrace();

                   }finally{

                            try{

                                     //關閉流,釋放資源

                                     fis.close();

                            }catch(Exception e){}

                   }

         }

}

         該示例代碼中,只使用一行代碼:

                   int i = fis.read(data);

         就實現了將流對象fis中的數據讀取到字節數組data中。該行代碼的作用是將fis流中的數據讀取出來,並依次存儲到數組data中,返回值為實際讀取的有效數據的個數。

         使用該中方式在進行讀取時,可以簡化讀取的代碼。

         當然,在讀取文件時,也可以使用Reader類的子類FileReader進行實現,在編寫代碼時,只需要將上面示例代碼中的byte數組替換成char數組即可。

使用FileReader讀取文件時,是按照char為單位進行讀取的,所以更適合於文本文件的讀取,而對於二進制文件或自定義格式的文件來說,還是使用FileInputStream進行讀取,方便對於讀取到的數據進行解析和操作。

讀取其它數據源的操作和讀取文件類似,最大的區別在於建立流對象時選擇的類不同,而流對象一旦建立,則基本的讀取方法是一樣,如果只使用最基本的read方法進行讀取,則使用基本上是一致的。這也是IO類設計的初衷,使得對於流對象的操作保持一致,簡化IO類使用的難度。

 程。

         基本的輸出流包含OutputStream和Writer兩個,區別是OutputStream體系中的類(也就是OutputStream的子類)是按照字節寫入的,而Writer體系中的類(也就是Writer的子類)是按照字符寫入的。

         使用輸出流進行編程的步驟是:

                   1、建立輸出流

                            建立對應的輸出流對象,也就是完成由流對象到外部數據源之間的轉換。

                   2、向流中寫入數據

                            將需要輸出的數據,調用對應的write方法寫入到流對象中。

                   3、關閉輸出流

                            在寫入完畢以后,調用流對象的close方法關閉輸出流,釋放資源。

         在使用輸出流向外部輸出數據時,程序員只需要將數據寫入流對象即可,底層的API實現將流對象中的內容寫入外部數據源,這個寫入的過程對於程序員來說是透明的,不需要專門書寫代碼實現。

         在向文件中輸出數據,也就是寫文件時,使用對應的文件輸出流,包括FileOutputStream和FileWriter兩個類,下面以FileOutputStream為例子說明輸出流的使用。示例代碼如下:

                   import java.io.*;

/**

 * 使用FileOutputStream寫文件示例

 */

public class WriteFile1 {

         public static void main(String[] args) {

                   String s = "Java語言";

                   int n = 100;

                   //聲明流對象

                   FileOutputStream fos = null;

                   try{

                            //創建流對象

                            fos = new FileOutputStream("e:\\out.txt");

                            //轉換為byte數組

                            byte[] b1 = s.getBytes();

                            //換行符

                            byte[] b2 = "\r\n".getBytes();

                            byte[] b3 = String.valueOf(n).getBytes();

                            //依次寫入文件

                            fos.write(b1);

                            fos.write(b2);

                            fos.write(b3);

                   } catch (Exception e) {

                            e.printStackTrace();

                   }finally{

                            try{

                                     fos.close();

                            }catch(Exception e){}

                   }

         }

}

         該示例代碼寫入的文件使用記事本打開以后,內容為:

                   Java語言

100

         在該示例代碼中,演示了將一個字符串和一個int類型的值依次寫入到同一個文件中。在寫入文件時,首先創建了一個文件輸出流對象fos:

                   fos = new FileOutputStream("e:\\out.txt");

         該對象創建以后,就實現了從流到外部數據源e:\out.txt的連接。說明:當外部文件不存在時,系統會自動創建該文件,但是如果文件路徑中包含未創建的目錄時將出現異常。這里書寫的文件路徑可以是絕對路徑也可以是相對路徑。

         在 實際寫入文件時,有兩種寫入文件的方式:覆蓋和追加。其中“覆蓋”是指清除原文件的內容,寫入新的內容,默認采用該種形式寫文件,“追加”是指在已有文件 的末尾寫入內容,保留原來的文件內容,例如寫日志文件時,一般采用追加。在實際使用時可以根據需要采用適合的形式,可以使用:

                   public FileOutputStream(String name, boolean append) throws FileNotFoundException

         只需要使用該構造方法在構造FileOutputStream對象時,將第二個參數append的值設置為true即可。

         流對象創建完成以后,就可以使用OutputStream中提供的wirte方法向流中依次寫入數據了。最基本的寫入方法只支持byte數組格式的數據,所以如果需要將內容寫入文件,則需要把對應的內容首先轉換為byte數組。

         這里以如下格式寫入數據:首先寫入字符串s,使用String類的getBytes方法將該字符串轉換為byte數組,然后寫入字符串“\r\n”,轉換方式同上,該字符串的作用是實現文本文件的換行顯示,最后寫入int數據n,首先將n轉換為字符串,再轉換為byte數組。這種寫入數據的順序以及轉換為byte數組的方式就是流的數據格式,也就是該文件的格式。因為這里寫的都是文本文件,所以寫入的內容以明文的形式顯示出來,也可以根據自己需要存儲的數據設定特定的文件格式。

         其實,所有的數據文件,包括圖片文件、聲音文件等等,都是以一定的數據格式存儲數據的,在保存該文件時,將需要保存的數據按照該文件的數據格式依次寫入即可,而在打開該文件時,將讀取到的數據按照該文件的格式解析成對應的邏輯即可。

         最后,在數據寫入到流內部以后,如果需要立即將寫入流內部的數據強制輸出到外部的數據源,則可以使用流對象的flush方法實現。如果不需要強制輸出,則只需要在寫入結束以后,關閉流對象即可。在關閉流對象時,系統首先將流中未輸出到數據源中的數據強制輸出,然后再釋放該流對象占用的內存空間。

         使用FileWriter寫入文件時,步驟和創建流對象的操作都和該示例代碼一致,只是在轉換數據時,需要將寫入的數據轉換為char數組,對於字符串來說,可以使用String中的toCharArray方法實現轉換,然后按照文件格式寫入數據即可。

         對於其它類型的字節輸出流/字符輸出流來說,只是在邏輯上連接不同的數據源,在創建對象的代碼上會存在一定的不同,但是一旦流對象創建完成以后,基本的寫入方法都是write方法,也需要首先將需要寫入的數據按照一定的格式轉換為對應的byte數組/char數組,然后依次寫入即可。

         所以IO類的這種設計形式,只需要熟悉該體系中的某一個類的使用以后,就可以觸類旁通的學會其它相同類型的類的使用,從而簡化程序員的學習,使得使用時保持統一。

(以上內容轉載自http://www.cnblogs.com/springcsc/archive/2009/12/03/1616367.html)

下面我們看文中的例子:

import java.io.*;

/**
 * 使用FileOutputStream寫文件示例
 */
public class WriteFile1 {
         public static void main(String[] args) {
                   String s = "Java語言";
                   int n = 100;
                   //聲明流對象
                   FileOutputStream fos = null;
                   try{
                            //創建流對象
                            fos = new FileOutputStream("e:\\out.txt");
                            //轉換為byte數組
                            byte[] b1 = s.getBytes();
                            //換行符
                            byte[] b2 = "\r\n".getBytes();
                            byte[] b3 = String.valueOf(n).getBytes();
                            //依次寫入文件
                            fos.write(b1);
                            fos.write(b2);
                            fos.write(b3);
                   } catch (Exception e) {
                            e.printStackTrace();
                   }finally{
                            try{
                                     fos.close();
                            }catch(Exception e){}
                   }
         }
}

也就是說輸出流包含:

java.io.*

聲明FileOutPutStream fos=null

try{

//完成創建輸出對象、轉換字節數組和寫入操作

創建對象:

 fos = new FileOutputStream("e:\\out.txt");
//其中"\\"是轉義字符

對於換行:

byte[] b2 = "\r\n".getBytes();

對於數字:

byte[] b3 = String.valueOf(n).getBytes();

對於字符:

 byte[] b1 = s.getBytes();

寫入:fos.write(b3);

}

catch(Exception e){

          e.printStackTrace();

                           }

finally{

      try{

         fos.close();

          }

      catch(Exception e){}

 

下面是一個輸出輸入數字內的質數的例子。

import java.io.*;
import java.util.Scanner;
public class zhishu_shuchu
{
    public static void main(String args[])
    {
        System.out.println("質數范圍,幾以內?");
        Scanner sc=new Scanner(System.in);
        int z=sc.nextInt();
        FileOutputStream fos=null;
        try{
        fos=new FileOutputStream("e:\\out.txt");
        for(int j=1;j<=z;++j)
        {
        boolean b=true;
        for(int i=2;i<=Math.sqrt(j);++i)
        {
            if(j%i==0)
            {
                b=false;
                break;
            }
        }
        if(j==1)
            b=false;
        if(b==true)
        {
            byte[] b1=String.valueOf(j).getBytes();
            byte[] b2="\r\n".getBytes();
            //String.valueOf(n).getBytes();
            //System.out.print(j+" ");
            fos.write(b1);
            fos.write(b2);
        }
        }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try{
                fos.close();
            }
            catch(Exception e){
            }
        }
    }
}

輸入:

100

輸出:out.txt

2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM