天天看點

Java IO整理總結之字元流

原文連結https://www.codeliu.com/java/266.html

上一篇文章中講了Java IO的位元組流,這次同樣的,先把整張圖搬上來

Java IO整理總結之字元流

字元流的類相對位元組流來說,沒有這麼多,但同樣重要。

**

字元流

**

一.Reader

Java IO整理總結之字元流

1.Reader

構造方法

Reader() 建立一個新的字元流 reader,其重要部分将同步其自身的 reader。

Reader(Object lock) 建立一個新的字元流 reader,其重要部分将同步給定的對象。

其他方法

void close() 關閉該流并釋放與之關聯的所有資源。

int read() 讀取單個字元

int read(char[] cbuf) 将字元讀入數組。

int read(char[] cbuf, int off, int len) 将字元讀入數組的某一部分。

int read(CharBuffer target) 試圖将字元讀入指定的字元緩沖區。

boolean ready() 判斷是否準備讀取此流。

void reset() 重置該流

long skip(long n) 跳過字元

2.BufferedReader

從字元輸入流中讀取文本,緩沖各個字元,進而實作字元、數組和行的高效讀取。

BufferedReader(Reader in) 建立一個使用預設大小輸入緩沖區的緩沖字元輸入流。

BufferedReader(Reader in, int sz) 建立一個使用指定大小輸入緩沖區的緩沖字元輸入流。

String readLine() 讀取一個文本行,不讀取換行

3.CharArrayReader

此類實作一個可用作字元輸入流的字元緩沖區。

CharArrayReader(char[] buf) 根據指定的 char 數組建立一個 CharArrayReader

CharArrayReader(char[] buf, int off, int len) 根據指定的 char 數組建立一個 CharArrayReader。

4.FilterReader

用于讀取已過濾的字元流的抽象類。抽象類 FilterReader 自身提供了一些将所有請求傳遞給所包含的流的預設方法。FilterReader 的子類應重寫這些方法中的一些方法,并且還可以提供一些額外的方法和字段。

FilterReader(Reader in) 建立一個新的 filtered reader。

5.InputStreamReader

InputStreamReader 是位元組流通向字元流的橋梁:它使用指定的 charset 讀取位元組并将其解碼為字元。它使用的字元集可以由名稱指定或顯式給定,或者可以接受平台預設的字元集。

InputStreamReader(InputStream in) 建立一個使用預設字元集的 InputStreamReader。

InputStreamReader(InputStream in, Charset cs) 建立使用給定字元集的 InputStreamReader。

InputStreamReader(InputStream in, CharsetDecoder dec) 建立使用給定字元集解碼器的 InputStreamReader。

InputStreamReader(InputStream in, String charsetName) 建立使用指定字元集的 InputStreamReader。

6.PipedReader

傳送的字元輸入流。

PipedReader() 建立尚未連接配接的 PipedReader。

PipedReader(int size) 建立一個尚未連接配接的 PipedReader,并對管道緩沖區使用指定的管道大小。

PipedReader(PipedWriter src) 建立連接配接到傳送 writer src 的 PipedReader。

PipedReader(PipedWriter src, int pipeSize) 建立一個 PipedReader,使其連接配接到管道 writer src,并對管道緩沖區使用指定的管道大小。

7.StringReader

其源為一個字元串的字元流。

StringReader(String s) 建立一個新字元串 reader。

二.Writer

Java IO整理總結之字元流

1.BufferedWriter

将文本寫入字元輸出流,緩沖各個字元,進而提供單個字元、數組和字元串的高效寫入。

BufferedWriter(Writer out) 建立一個使用預設大小輸出緩沖區的緩沖字元輸出流。

BufferedWriter(Writer out, int sz) 建立一個使用給定大小輸出緩沖區的新緩沖字元輸出流。

void close() 關閉此流,但要先重新整理它

void flush() 重新整理該流的緩沖區

void newLine() 寫入一個行分隔符

void write(char[] buf, int off, int len) 寫入字元數組的某一部分

void write(int c) 寫入單個字元

void write(String s, int off, int len) 寫入字元串的某一部分

2.CharArrayWriter

此類實作一個可用作 Writer 的字元緩沖區。緩沖區會随向流中寫入資料而自動增長。可使用 toCharArray() 和 toString() 擷取資料。

CharArrayWriter() 建立一個新的CharArrayWriter

CharArrayWriter(int size) 建立一個具有指定初始大小的新 CharArrayWriter。

CharArrayWriter append(char c) 将指定字元添加到此 writer。

CharArrayWriter append(CharSequence csq) 将指定的字元序列添加到此 writer。

CharArrayWriter append(CharSequence csq, int start, int end) 将指定字元序列的子序列添加到此 writer。

int size() 傳回緩沖區的目前大小

char[] toCharArray() 傳回輸入資料的副本

String toString() 将輸入資料轉換為字元串

void writeTo(Write out) 将緩沖區的内容寫入另一字元流

3.FilterWriter

用于寫入已過濾的字元流的抽象類。抽象類 FilterWriter 自身提供了一些将所有請求傳遞給所包含的流的預設方法。FilterWriter 的子類應重寫這些方法中的一些方法,并且還可以提供一些額外的方法和字段。

FilterWriter(Writer out) 建立一個新的 filtered writer。

4.OutputStreamWriter

OutputStreamWriter 是字元流通向位元組流的橋梁:可使用指定的 charset 将要寫入流中的字元編碼成位元組。它使用的字元集可以由名稱指定或顯式給定,否則将接受平台預設的字元集。

OutputStreamWriter(OutputStream out) 建立使用預設字元編碼的 OutputStreamWriter。

OutputStreamWriter(OutputStream out, Charset cs) 建立使用給定字元集的 OutputStreamWriter。

OutputStreamWriter(OutputStream out, CharsetEncoder enc) 建立使用給定字元集編碼器的 OutputStreamWriter。

OutputStreamWriter(OutputStream out, String charsetName) 建立使用指定字元集的 OutputStreamWriter。

5.PipedWriter

傳送的字元輸出流。

PipedWriter() 建立一個尚未連接配接到傳送 reader 的傳送 writer。

PipedWriter(PipedReader snk) 建立傳送 writer,使其連接配接到指定的傳送 reader

6.StringWriter

一個字元流,可以用其回收在字元串緩沖區中的輸出來構造字元串。

StringWriter() 使用預設初始字元串緩沖區大小建立一個新字元串 writer。

StringWriter(int initialSize) 使用指定初始字元串緩沖區大小建立一個新字元串 writer。

StringWriter append(char c) 将指定字元添加到此 writer。

StringWriter append(CharSequence csq) 将指定的字元序列添加到此 writer。

StringWriter append(CharSequence csq, int start, int end) 将指定字元序列的子序列添加到此 writer。

StringBuffer getBuffer() 傳回該字元串緩沖區本身。

String toString() 以字元串的形式傳回該緩沖區的目前值。

void write(String str) 寫入一個字元串

下面我們來看看代碼

/**
 * @author liu 
 * @version 建立時間:2018年3月5日 下午6:00:49 
 * 類說明 BufferedReader BufferedWriter PrintWriter 
 */
 public class BrAndBwOrPw { 
     public static void main(String[] args) throws IOException{ 
         BufferedReader br = new BufferedReader( new InputStreamReader(new FileInputStream("demo\\test.txt"))); 
         BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(new FileOutputStream("demo\\test2.txt"))); 
         PrintWriter pw = new PrintWriter("demo\\test3.txt"); 
         String s; 
         while((s = br.readLine()) != null) { 
             // 不讀取換行 
             //System.out.print(s);   
             System.out.println(s); 
             bw.write(s); 
             // 換行 
             bw.newLine(); 
             pw.println(s); 
         } 
         bw.flush(); 
         br.close();
         bw.close(); 
         pw.flush();
         pw.close(); 
     }
}           
/**
 * @author liu 
 * @version 建立時間:2018年3月5日 下午5:47:06
 * 類說明 FileReader FileWriter 
 */
public class FrAndFw { 
    public static void main(String[] args) throws IOException{ 
        // 構造函數不能設定字元編碼,預設gbk,如果讀取其他類型的編碼,會出現亂碼 
        FileReader fr = new FileReader("demo\\test.txt"); 
        // 加true表示在後面追加 
        //FileWriter fw = new FileWriter("demo\\test1.txt", true); 
        FileWriter fw = new FileWriter("demo\\test1.txt"); 
        int b; 
        while((b = fr.read()) != -1) { 
            System.out.print((char)b); 
            fw.write(b); 
        } 
        // 記得重新整理 
        fw.flush(); 
        fr.close(); 
        fw.close(); 
    }
}           
/**
 * @author liu
 * @version 建立時間:2018年3月5日 下午4:48:15
 * 類說明 InputStreamReader OutputStreamReader 
 */
public class IsrAndOsrDemo { 
    public static void main(String[] args) throws IOException{ 
        FileInputStream in = new FileInputStream("demo\\test.txt"); 
        // 預設gbk編碼,應使用項目具體要的編碼格式 
        InputStreamReader isr = new InputStreamReader(in); 
        //InputStreamReader isr1 = new InputStreamReader(in, "utf-8"); 
        //FileOutputStream out = new FileOutputStream("demo\\test1.txt"); 
        //int b; 
        //while((b = isr.read()) != -1) { 
            //System.out.print((char)b); 
        //} 
        byte[] buf = new byte[8 * 1024]; 
        int c; 
        while((c = in.read(buf, 0, buf.length)) != -1) { 
            String s = new String(buf, 0, c); 
            System.out.print(s); 
        } 
    }
}           
RandomAccessFile

此類的執行個體支援對随機通路檔案的讀取和寫入。随機通路檔案的行為類似存儲在檔案系統中的一個大型 byte 數組。存在指向該隐含數組的光标或索引,稱為檔案指針;輸入操作從檔案指針開始讀取位元組,并随着對位元組的讀取而前移此檔案指針。如果随機通路檔案以讀取/寫入模式建立,則輸出操作也可用;輸出操作從檔案指針開始寫入位元組,并随着對位元組的寫入而前移此檔案指針。寫入隐含數組的目前末尾之後的輸出操作導緻該數組擴充。該檔案指針可以通過 getFilePointer 方法讀取,并通過 seek 方法設定。

通常,如果此類中的所有讀取例程在讀取所需數量的位元組之前已到達檔案末尾,則抛出 EOFException(是一種 IOException)。如果由于某些原因無法讀取任何位元組,而不是在讀取所需數量的位元組之前已到達檔案末尾,則抛出 IOException,而不是 EOFException。需要特别指出的是,如果流已被關閉,則可能抛出 IOException。

RandomAccessFile适用于由大小已知的記錄組成的檔案。

RandomAccessFile(File file, String mode) 建立從中讀取和向其中寫入(可選)的随機通路檔案流,該檔案由 File 參數指定。

RandomAccessFile(String name, String mode) 建立從中讀取和向其中寫入(可選)的随機通路檔案流,該檔案具有指定名稱。

long getFilePointer() 傳回此檔案中的目前偏移量

long length() 傳回此檔案的長度

int read() 從此檔案中讀取一個資料位元組

int read(byte[] b) 将最多 b.length 個資料位元組從此檔案讀入 byte 數組。

int read(byte[] b, int off, int len) 将最多 len 個資料位元組從此檔案讀入 byte 數組。

boolean readBoolean() 從此檔案讀取一個boolean

。。。。包括int readInt() 之類的方法,具體看手冊

void seek(long pos) 設定到此檔案開頭測量到的檔案指針偏移量,在該位置發生下一個讀取或寫入操作。

void setLength(long newLength) 設定此檔案的長度。

void write(byte[] b) 将 b.length 個位元組從指定 byte 數組寫入到此檔案,并從目前檔案指針開始。

void write(int b) 向此檔案寫入指定的位元組

void write(byte[] b , int off, int len) 将 len 個位元組從指定 byte 數組寫入到此檔案,并從偏移量 off 處開始。

void writeBoolean(boolean v) 按單位元組值将 boolean 寫入該檔案

。。。。包括void writeInt() 之類的方法,具體看手冊

下面看看代碼

/**
 * @author liu
 * @version 建立時間:2018年3月2日 下午3:48:44
 * RandomAccessFile類的使用 
 */
public class RafDemo { 
    public static void main(String[] args) throws IOException { 
        // 相對路徑 
        File demo = new File("demo"); 
        if(!demo.exists()) { 
            demo.mkdir(); 
        } 
        // demo檔案夾下的test.txt 
        File file = new File(demo, "test.txt"); 
        if(!file.exists()) { 
            file.createNewFile(); 
        } 
        RandomAccessFile raf = new RandomAccessFile(file, "rw"); 
        // 傳回目前指針的位置 
        System.out.println(raf.getFilePointer()); 
        // 一次隻能寫一個位元組,所有寫入A的後八位 
        raf.write('A'); 
        System.out.println(raf.getFilePointer()); 
        raf.write('B'); 
        int x = 0x7fffffff; 
        // 寫入高8位 
        raf.write(x >>> 24);  
        raf.write(x >>> 16); 
        raf.write(x >>> 8); 
        raf.write(x); 
        System.out.println(raf.getFilePointer()); 
        // 直接寫入一個整數 
        raf.writeInt(x); 
        String s = "中"; 
        byte[] gbk = s.getBytes("gbk"); 
        raf.write(gbk); 
        System.out.println(raf.length()); 
        // 讀檔案,必須把指針移到頭部 
        raf.seek(0); 
        // 一次性讀取,raf.length傳回的是long類型 
        byte[] readF = new byte[(int) raf.length()]; 
        raf.read(readF); 
        System.out.println(Arrays.toString(readF)); 
        for(byte b:readF) { 
            System.out.print(Integer.toHexString(b) + "  "); 
        } 
        // 記得關閉檔案 
        raf.close(); 
    }
}           
總結

Java IO 的一般使用原則 :

一、按資料來源(去向)分類:

1 、是檔案: FileInputStream, FileOutputStream, ( 位元組流 )FileReader, FileWriter( 字元 )

2 、是 byte[] : ByteArrayInputStream, ByteArrayOutputStream( 位元組流 )

3 、是 Char[]: CharArrayReader, CharArrayWriter( 字元流 )

4 、是 String: StringBufferInputStream, StringBufferOuputStream ( 位元組流 )StringReader, StringWriter( 字元流 )

5 、網絡資料流: InputStream, OutputStream,( 位元組流 ) Reader, Writer( 字元流 )

二、按是否格式化輸出分:

1 、要格式化輸出: PrintStream, PrintWriter

三、按是否要緩沖分:

1 、要緩沖: BufferedInputStream, BufferedOutputStream,( 位元組流 ) BufferedReader, BufferedWriter( 字元流 )

四、按資料格式分:

1 、二進制格式(隻要不能确定是純文字的) : InputStream, OutputStream 及其所有帶 Stream 結束的子類

2 、純文字格式(含純英文與漢字或其他編碼方式); Reader, Writer 及其所有帶 Reader, Writer 的子類

五、按輸入輸出分:

1 、輸入: Reader, InputStream 類型的子類

2 、輸出: Writer, OutputStream 類型的子類

六、特殊需要:

1 、從 Stream 到 Reader,Writer 的轉換類: InputStreamReader, OutputStreamWriter

2 、對象輸入輸出: ObjectInputStream, ObjectOutputStream

3 、程序間通信: PipeInputStream, PipeOutputStream, PipeReader, PipeWriter

4 、合并輸入: SequenceInputStream

5 、更特殊的需要: PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader

決定使用哪個類以及它的構造程序的一般準則如下(不考慮特殊需要):

首先,考慮最原始的資料格式是什麼: 原則四

第二,是輸入還是輸出:原則五

第三,是否需要轉換流:原則六第 1 點