1. 程式人生 > >2017java檔案操作(讀寫操作)

2017java檔案操作(讀寫操作)

java的讀寫操作是學java開發的必經之路,下面就來總結下java的讀寫操作。

從上圖可以開出,java的讀寫操作(輸入輸出)可以用“流”這個概念來表示,總體而言,java的讀寫操作又分為兩種:字元流和位元組流。

什麼是流?

流是一個抽象的概念。當Java程式需要從資料來源讀取資料時,會開啟一個到資料來源的流。資料來源可以是檔案,記憶體或者網路等。同樣,當程式需要輸出資料到目的地時也一樣會開啟一個流,資料目的地也可以是檔案、記憶體或者網路等。流的建立是為了更方便地處理資料的輸入輸出。

那麼位元組流和字元流又有什麼區別呢?

1.位元組流也稱為原始資料,需要使用者讀入後進行相應的編碼轉換。而字元流的實現是基於自動轉換的,讀取資料時會把資料按照JVM的預設編碼自動轉換成字元。

2.字元流處理的單元為2個位元組的Unicode字元,分別操作字元、字元陣列或字串,而位元組流處理單元為1個位元組,操作位元組和位元組陣列。

所以字元流是由Java虛擬機器將位元組轉化為2個位元組的Unicode字元為單位的字元而成的。

3.位元組流可用於任何型別的物件,包括二進位制物件,而字元流只能處理字元或者字串,位元組流提供了處理任何型別的IO操作的功能,但它不能直接處理Unicode字元,而字元流就可以;

基於以上的區別,那麼什麼情況下用字元流,什麼情況下用位元組流呢?

如果是音訊檔案、圖片、歌曲,就用位元組流好點;如果是中文(文字)的,用字元流更好;

說了這麼多,位元組流和字元流處理檔案到底怎麼用呢?

稍安勿躁,讓我們先來看看在java中,輸入輸出操作的步驟是什麼?

1 使用File類開啟一個檔案

通過位元組流或字元流的子類,指定輸出的位置,注,

3 進行讀/寫操作

4 關閉輸入/輸出

IO操作屬於資源操作,一定要記得關閉

位元組流:

1.按照位元組流的方式從檔案中讀取資料。

package ioInJava.characterStream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream; public class CharIo { public static void main(String[] args) { // 第一種方式讀檔案,因為方法throws了異常,所以在這要捕獲異常 try { CharIo.readFromFileByByte(); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("找不到檔案啊"); } catch (IOException e) { e.printStackTrace(); System.out.println("讀不成功啊!"); } System.out.println("==========================="); // 第二種方式讀檔案 try { CharIo.readFromFileByteTwo(); } catch (IOException e) { e.printStackTrace(); System.out.println("還是讀不成功啊!"); } } /** * 第一種方法讀檔案 * 通過字元流讀取檔案中的資料 * @throws IOException */ public static void readFromFileByByte() throws IOException{ File file = new File("abc.txt"); // 如果檔案不存在則建立檔案 if (!file.exists()) { file.createNewFile(); } InputStream inputStream = new FileInputStream(file); // 這裡定義了陣列的長度是1024個位元組,如果檔案超出這位元組,就會溢位,結果就是讀不到1024位元組以後的東西 byte[] bs = new byte[1024]; // 這裡len獲得的是檔案中內容的長度 int len = inputStream.read(bs); inputStream.close(); System.out.println(new String(bs)); } /** * 第二種方法讀檔案 * 通過字元流讀取檔案中的資料 * @throws IOException */ public static void readFromFileByteTwo() throws IOException{ // 注意這裡的不同,File.separator是分隔符,這裡指明絕對路徑,即D盤根目錄下的abc.txt檔案 File file = new File("d:" + File.separator+"abc.txt"); // 如果檔案不存在則建立檔案 if (!file.exists()) { file.createNewFile(); } InputStream inputStream = new FileInputStream(file); // 這裡也有不同,可以根據檔案的大小來宣告byte陣列的大小,確保能把檔案讀完 byte[] bs = new byte[(int)file.length()]; // read()方法每次只能讀一個byte的內容 inputStream.read(bs); inputStream.close(); System.out.println(new String(bs)); } }

2.按照位元組流的方式向檔案中寫入資料。

package ioInJava.byteStream;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
 * 不要被那麼多的try和catch嚇到奧,那只是因為不想在main上throws
 * @author wsg
 */
public class WriteToFile {

    public static void main(String[] args) {
        File file = new File("D:"+File.separator+"write.doc");
        OutputStream outputStream = null;
        if (!file.exists()) {
            try {
                // 如果檔案找不到,就new一個
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            // 定義輸出流,寫入檔案的流
            outputStream = new FileOutputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 定義將要寫入檔案的資料
        String string = "Hell Java, Hello World, 你好,世界!";
        // 把string轉換成byte型的,並存放在陣列中
        byte[] bs = string.getBytes();
        try {
            // 寫入bs中的資料到file中
            outputStream.write(bs);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        try {
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // =================到此,檔案的寫入已經完成了!
        
        // 如果想在檔案後面追加內容的話,用下面的方法
        OutputStream outToFileEnd = null;
        try {
            outToFileEnd = new FileOutputStream(file,true);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {// 這裡利用了finally總會被執行的特性,索性把後面的程式碼都寫在finally中
            String string2 = "Here I come!!";
            byte[] bs2 = string2.getBytes();
            try {
                outToFileEnd.write(bs2);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    outToFileEnd.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

=====================================================注意!!==================================================

1.初學者一般很容易搞混,或者弄不清inputstream和outpustream到底哪個是讀資料,哪個是寫資料,這裡要說明的是,“讀和寫”是相對於程式本身而言的,主要記清楚一點即可,那就是凡是需要提供給程式處理的資料就是輸入資料,當然就是inputstream,這裡的in是要in到程式裡面去,那麼資料從哪裡來呢,自然是從外界(網路,記憶體或者檔案),那麼針對檔案而言,inputstream就是讀檔案了。反之,凡是程式已經處理過的資料,當然要流出程式啦,那就是out咯,所以outputstream就是輸出的,那麼從程式中流出,只能到外界(網路、記憶體或者檔案),針對檔案而言,就是寫操作啦!(同樣的道理可以針對字元流的操作)

【簡言之,針對程式而言,in是入,out是出;這對檔案而言,in是讀,out是寫!】

2.inputstream和OutputStream都是抽象類,不能例項化,使用時必須例項化一個子類(其中FileInputStream和FileOutputStream使用最多)物件來進行相關操作。

3.InputStream inputStream = new FileInputStream(fileName);當使用這個命令時,系統會提示有異常丟擲,因為我們上面定義的檔案程式認為是有可能存在,有可能不存在的,所以在eclipse中,給出了兩個解決辦法,一個是直接丟擲異常宣告,由系統自己解決;另一個是用try,catch結構處理異常!

===============================================================================================================

3.按照字元流的方式向檔案中寫入資料。

package ioInJava.characterStream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;

public class CharIo {

    public static void main(String[] args) throws IOException {
        // 定義一個d盤根目錄下的test文件,File.separator是分隔符
        // 下面這句程式碼,就算原本沒有這個檔案,也會在對應的目錄建立一個檔案
        File file = new File("D:" + File.separator + "test.docx");
        // 下面這也會丟擲異常,這次我們為了程式碼結構清晰起見,直接throw給main吧
        Writer writer = new FileWriter(file);
        String string = "今天是教師節!";
        writer.write(string);
        // 在這一定要記得關閉流
        writer.close();
    }
}

但是,上面的程式碼有一個問題,比如,載定義一個string2,再次呼叫writer.write(string2)方法的時候,會發現test檔案中的內容會被string2的內容覆蓋,要想實現內容追加到檔案尾部,程式碼如下,其實就是小小的修改,利用它的一個方法!

package ioInJava.characterStream;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;

public class CharIo {

    public static void main(String[] args) throws IOException {
        // 定義一個d盤根目錄下的test文件,File.separator是分隔符
        // 下面這句程式碼,就算原本沒有這個檔案,也會在對應的目錄建立一個檔案
        File file = new File("D:" + File.separator + "test.docx");
        // 下面這也會丟擲異常,這次我們為了程式碼結構清晰起見,直接throw給main吧
        // 這裡改變了writer的型別,變成了追加型
        Writer writer = new FileWriter(file, true);
        String string = "今天是教師節!";
        writer.write(string);
        String string2 = "祝願所有的老師教師節快樂!";
        writer.write(string2);;
        // 在這一定要記得關閉流
        writer.close();
    }
}

4.按照字元流的方式從檔案中讀取資料。

package ioInJava.characterStream;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;

public class ReadFromFile {

    public static void main(String[] args) throws IOException {
        File file = new File("d:" + File.separator + "test.docx");
        Reader reader = new FileReader(file);
        char[] cs= new char[1024];
        // 上面定義了一個大小為1024的char型陣列,如果檔案內容過大,程式就會報錯,而不是隻讀到1024的大小
        reader.read(cs, 0, (int)file.length());
        System.out.println(cs);
        reader.close();
    }

}

上面的程式碼只能讀取內容不超過1024字元的內容,這顯然不是我們想要的,如何讀取一個任意大小的檔案呢!那麼最簡單的方法就是加大陣列的空間大小了,可以用file.length獲取檔案的大小,從而定義陣列的大小!char[] cs= new char[(int)file.length()];

當然,這不是最好的辦法,請看下面的程式碼:

package ioInJava.characterStream;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

public class ReadFromFile {

    public static void main(String[] args) throws IOException {
        try {
            // 宣告一個可變長的stringBuffer物件
            StringBuffer sb = new StringBuffer("");
            
            /*
             * 讀取完整檔案
             */
            Reader reader = new FileReader("d:" + File.separator + "test.docx");
            // 這裡我們用到了字元操作的BufferedReader類
            BufferedReader bufferedReader = new BufferedReader(reader);
            String string = null;
            // 按行讀取,結束的判斷是是否為null,按位元組或者字元讀取時結束的標誌是-1
            while ((string = bufferedReader.readLine()) != null) {
                // 這裡我們用到了StringBuffer的append方法,這個比string的“+”要高效
                sb.append(string + "/n");
                System.out.println(string);
            }
            // 注意這兩個關閉的順序
            bufferedReader.close();
            reader.close();
            
            /*
             * 完整寫入檔案
             */
            Writer writer = new FileWriter("d:" + File.separator + "test2.docx");
            BufferedWriter bw = new BufferedWriter(writer);
            // 注意這裡呼叫了toString方法
            bw.write(sb.toString());
            // 注意這兩個關閉的順序
            bw.close();
            writer.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

上面的程式碼我們順利實現了從test檔案中讀取全文,並將其寫入test2檔案中!!

摘自:https://www.cnblogs.com/wsg25/p/7499227.html