【轉】輸入/輸出流 - 全面掌握IO

來源:互聯網
上載者:User

標籤:

File類:

程式中操作檔案和目錄都可以使用File類來完成即不管是檔案還是目錄都是使用File類來操作的,File能建立,刪除,重新命名檔案和目錄,但File不能訪問檔案內容本身,如果需要訪問檔案本身,則需要使用輸入/輸出流,該類是位於java.io包下的

輸入與輸出IO:

輸入資料流:只能從中讀取資料,而不能向其中寫入資料(由InputStream(位元組流)和Reader(字元流)作為基類)

輸出資料流:只能向其寫入資料,而不能從中讀取資料(由OutputStream(位元組流)和Writer(字元流)作為基類)

java的io總共涉及40多個類,但都是從這四個抽象基類中派生出來的

 

InputStream最重要的三個read方法:

Reader中的read方法:

從這兩個抽象類別提供的方法就可以看出其實功能基本是一樣的,只是操作的資料單元不一樣而已

由於InputStream與Reader都是抽象類別,是不能進行執行個體化的,我們只能用他們的子類來建立執行個體,它們分別提供了一個子類用於讀取檔案的輸入資料流:FileInputStream和

FileReader,這兩個子類都是節點流(與處理流相對)-----會直接與指定的檔案關聯而無封裝。下面代碼示範FileInputStream使用read(byte[] b):

package xidian.sl.io;import java.io.FileInputStream;import java.io.FileReader;public class InputStreamTest {    /**     * 使用FileInputStream讀取該類本身     * */    public static void FileInputStreamTest() throws Exception{        FileInputStream fis = null;        try{        //建立位元組輸入資料流        fis = new FileInputStream("src/xidian/sl/io/InputStreamTest.java");        //建立一個長度為1024的位元組數組來存取        byte[] bbuf = new byte[1024];        //用於儲存實際讀取的位元組數        int hasRead = 0;        //使用迴圈來進行重複讀取        while((hasRead = fis.read(bbuf))> 0){            //取出位元組,將位元組數組轉化為字串輸出            System.out.println(new String(bbuf, 0 , hasRead));        }        }finally{            //關閉檔案輸入資料流            fis.close();        }    }    /**     * 使用FileReader讀取該類本身     * */    public static void FileReaderTest() throws Exception{            FileReader fr = null;        try{        //建立位元組輸入資料流        fr = new FileReader("src/xidian/sl/io/InputStreamTest.java");        //建立一個長度為1024的位元組數組來存取        char[] bbuf = new char[40];        //用於儲存實際讀取的位元組數        int hasRead = 0;        //使用迴圈來進行重複讀取        while((hasRead = fr.read(bbuf))> 0){            //取出位元組,將位元組數組轉化為字串輸出            System.out.println(new String(bbuf, 0 , hasRead));        }        }finally{            //關閉檔案輸入資料流            fr.close();        }    }    public static void main(String[] args) throws Exception{        InputStreamTest.FileInputStreamTest();        InputStreamTest.FileReaderTest();    }}

可以看到這兩個子類的使用方式可以說是完全一樣的,不過這裡要注意一個問題:位元組流FileInputStream是根據位元組來讀取的,而一個中文是佔兩個位元組的,如果包含很多中文的檔案被位元組流分多次進行讀取,可能會造成亂碼,因為有可能會導致剛好將一個中文分兩次讀取,這樣就會亂碼了,因此如果中文包含多的話還是使用字元流FileReader比較好,

在位元組流與字元流之間選擇的規律:如果需要進行輸入/輸出的內容是常值內容,則應該考慮使用字元流,如果需要進行輸入/輸出的是二進位內容,則應該考慮使用位元組流,因為位元組流的功能比字元流強大,電腦中所有的資料都是二進位的,而位元組流可以處理所有的二進位檔案;

 

OutputStream中最重要的write方法:

Writer中最重要的write方法:

Writer類中多了兩個對字串的操作類,因此如果是直接輸出字串就選用Writer會比較的方便;

與輸入資料流一樣,輸出資料流也有兩個檔案操作的子類:FileOutputStream和FileWrite

package xidian.sl.io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileWriter;public class OutputStreamTest {    /**     * 使用位元組流輸出     * */    public static void FileOutputStreamTest() throws Exception{        FileInputStream fis = null;        FileOutputStream fos = null;        try{            //建立位元組輸入資料流            fis = new FileInputStream("src/xidian/sl/io/InputStreamTest.java");            //建立位元組輸出資料流            fos = new FileOutputStream("src/xidian/sl/io/Output.txt");            byte[] bt = new byte[40];            int hasRead = 0;            //迴圈從輸入資料流中讀取資料            while((hasRead = fis.read(bt))> 0){                //每讀取一個,即寫入檔案輸出資料流,讀了多少就寫多少                fos.write(bt, 0, hasRead);            }                    }catch (Exception e) {            e.printStackTrace();        }finally{            /**             * 流在關閉時會自動執行flash,將緩衝中的資料flush到物理節點中             * 所以關閉時很重要的             * */            if(fis != null){                fis.close();            }            if(fos != null){                fos.close();            }        }    }    /**     * 使用字元流輸出字串會顯得比較的方便     * */    public static void FileWriteTest() throws Exception{        FileWriter fw = null;        try{            //建立位元組輸出資料流            fw = new FileWriter("src/xidian/sl/io/Output.txt");            fw.write("溫州醫學院\r\n");            fw.write("資訊與管理專業\r\n");            fw.write("溫州醫學院\r\n");            fw.write("溫州醫學院\n");            fw.write("溫州醫學院");        }catch (Exception e) {            e.printStackTrace();        }finally{            if(fw != null){                fw.close();            }        }    }    public static void main(String[] args) throws Exception{        OutputStreamTest.FileOutputStreamTest();        OutputStreamTest.FileWriteTest();    }}


 

上面是節點流的基本使用,下面將瞭解處理流的使用,處理流會顯得更加的高效

區分節點流於處理流的方法是:只要流的構造器的參數不是一個物理節點,而是已存在的流,那這個流一定是處理流,因為所有的節點流都是直接以物理io節點作為構造器的參數、

(如file)。

舉例:PrintStream處理流來封裝FileOutputStream節點流,進行輸出,由於PrintStream類的輸出功能非常的強大,因此我們需要輸出常值內容一般都會將輸出資料流封裝成PrintStream後輸出

package xidian.sl.io;import java.io.FileOutputStream;import java.io.PrintStream;public class PrintStreamTest {    public static void main(String[] args){        PrintStream ps = null;        try{            //建立一個節點輸出資料流            FileOutputStream fos = new FileOutputStream("src/xidian/sl/io/Output.txt");            //以PrintStream處理流來封裝FileOutputStream節點流            ps = new PrintStream(fos);            ps.println("一般字元串");            ps.println(new PrintStreamTest());        }catch (Exception e) {            e.printStackTrace();        }finally{            ps.close();        }    }}

其實我們一直使用的標準輸出System.out的類型都是PrintStream:

從上面的執行個體就可以看出將節點流封裝成處理流很簡單,只需調用處理流的構造方法來傳入節點流就可以了;而且看到上面流的關閉只是關閉了處理流而未去關閉節點流,這樣做是完全正確的,以後我們在關閉流的時候只需要關閉最上層的處理流即可;

 

字元流中有兩個特別的流來處理字串的:StringReader和StringWriter,

可以看到使用時執行個體化只需要傳入一個字串即可:例子:

package xidian.sl.io;import java.io.StringReader;import java.io.StringWriter;public class StringNodeTest {    /**     * @param args     */    public static void main(String[] args) {        // TODO Auto-generated method stub        String src = "你是個神";        StringReader sr = new StringReader(src);        char[] chars = new char[40];        int hasRead = 0;        try{            //採用迴圈的方式            while((hasRead = sr.read(chars))>0){                System.out.println(new String(chars, 0, hasRead));            }        }catch (Exception e) {            e.printStackTrace();        }finally{            sr.close();        }        //建立StringWriter        StringWriter sw = new StringWriter(40);        sw.write("你是一個大神");        sw.write("你也是一個大神");        System.out.println(sw.toString());            }}


io系統提供的兩個轉換流:InputStreamReader和OutputStreamWriter,都是將位元組流轉化為字元流

在java中是使用System.in來提供鍵盤輸入的,但這個標準輸入資料流是InputStream類的執行個體:

而前面講到了當處理的是常值內容時,使用字元流會顯得比較方便,正好鍵盤輸入就是文本的操作,因此我們有必須將System.in轉換為字元流:

package xidian.sl.io;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class KeyinTest {    public static void main(String[] args){        BufferedReader br = null;        try{            //將System.in對象轉化為Reader對象            InputStreamReader isr = new InputStreamReader(System.in);            //將節點流封裝為處理流            br = new BufferedReader(isr);            String buffer = null;            //採用迴圈的方式一行一行讀取            while((buffer = br.readLine()) != null){                System.out.print("輸入的內容 = "+ buffer);            }        }catch (Exception e) {            e.printStackTrace();        }finally{            try {                br.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }}

PrintStream是有強大的輸出功能,而BufferReader有強大的輸入(即讀取),因此在操作讀取常值內容時儘可能將其轉化為BufferReader,可以方便的使用readLine()方法

 

 接下來最為強大的檔案操作類RandomAccessFile來了,這個類既可以向檔案輸入資料,也可以輸出資料,並且他與不同的流最大的不同就是“支援檔案任意位置的訪問”,即程式可以控制讀取檔案哪個位置的內容;

從構造方法上可以看出,除了提供一個檔案或檔案名稱外還需要提供一個String參數mode,mode規定了RandomAccessFile類訪問檔案的模式:

1. “r”:以唯讀方式開啟指定檔案

2. “rw”:以讀取,寫入方式開啟指定檔案,並且檔案不存在會自動進行建立

3.“rws”與“rwd”:與“rw”類似,只是要求檔案內容或中繼資料的每個更新都同步寫入底層存放裝置

【轉】輸入/輸出流 - 全面掌握IO

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.