程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> 【JAVA I/O】字符輸入流Reader簡要概括

【JAVA I/O】字符輸入流Reader簡要概括

編輯:JAVA編程入門知識

字符輸入流Reader組成結構

本篇將對JAVA I/O流中的字符輸入流Reader做個簡單的概括,先看下Reader的組成結構(下圖);

總得來說,以上每個字符流類都有一個對應的用途,可以如下劃分:

  • 字符流基類:Reader
  • 字節流轉字符流:InputStreamReader
  • 字符文件讀取相關:FileReader
  • 字符數組轉字符流:CharArrayReader
  • 線程內部通信(管道):PipedReader
  • 緩沖流:BufferedReader
  • 過濾流:FilterReader
  • 字符串轉字符流:StringReader
  • Parse Input:PushbackReader(可以回退讀取)、LineNumberReader(顯示行號)

下面將對各個字符輸入流做個詳細介紹;

InputStreamReader

InputStreamReader繼承字符流抽象類Reader,每個構造方法都包含一個字節流InputStream入參,功能顯而易見,就是通過字節流InputStream得到字符流;

PS:無論是構造方法裡對字節流的處理(StreamDecoder.forInputStreamReader),還是字符流的讀取(StreamDecoder.read),底層都是通過StreamDecoder類實現的,有興趣的可以深入了解~

 舉個例子,如下,為方便閱讀,不做異常處理:

package io;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

public class IOTest {

    public static void main(String[] args) throws IOException  {
        //通過“標准”字節輸入流得到一個字符輸入流
        Reader reader = new InputStreamReader(System.in);
        //讀取一個字符並打印
        System.out.println((char)reader.read());
        //關閉流
        reader.close();
    }
}
//輸出示例
//鍵盤輸入0
//顯示0

FileReader

FileReader繼承字符流InputStreamReader,通過本地字符文件得到字符流,查看其構造方法,都是先根據傳入的參數生成一個FileInputStream字節流對象,然後調用父類InputStreamReader的構造方法得到字符流;

舉個簡單的例子:

package io;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class IOTest {

    public static void main(String[] args) throws IOException  {
        //讀取本地文件,得到字符流
        Reader reader = new FileReader("C:\\test.txt");
        //讀取一個字符並打印
        System.out.println((char)reader.read());
        //關閉流
        reader.close();
    }
}

CharArrayReader

CharArrayReader可以讓我們通過字符數組得到字符流,構造方法如下

查看源碼,可以發現在CharArrayReader裡面直接使用外部字符數組的引用,也就是說,即使得到字符流對象後,當改變外部數組時,通過流讀取的字符也會改變,如下代碼實例:

package io;

import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;

public class IOTest {

    public static void main(String[] args) throws IOException  {
        //字符數組
        char[] charArr = new char[]{'a', 'b', 'c'};
        //通過內存中的字符數組,得到字符流
        Reader reader = new CharArrayReader(charArr);
        //改變數組charArr的元素值
        charArr[0] = 'e';
        //讀取一個字符並打印
        System.out.println((char)reader.read());//打印改變後的字符'e'
        //關閉流
        reader.close();
    }
}

PipedReader

可以通過PipedWriter和PipedReader創建字符流管道,線程間可以通過管道進行通信,注意:一定要同一個JVM中的兩個線程;

PipedReader一般是要和PipedWriter配合使用的,其中一個線程通過PipedWriter往管道寫數據,另一個線程通過管道讀數據,注意讀寫都會阻塞線程,如下示例:

package io;

import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class IOTest {

    public static void main(String[] args) throws IOException {
        final PipedWriter pw = new PipedWriter();
        final PipedReader pr = new PipedReader(pw);

        ExecutorService es = Executors.newFixedThreadPool(2);

        es.execute(new Runnable() {

            @Override
            public void run() {
                try {
                    pw.write("hello~");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

        es.execute(new Runnable() {

            @Override
            public void run() {

                char[] cbuffer = new char[6];
                try {
                    // 會導致線程阻塞
                    pr.read(cbuffer, 0, 6);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                System.out.println(cbuffer);

            }
        });

    }
}

BufferedReader

這個字符流可以用來裝飾其它字符輸入流,可以為其它字符輸入流提供字符緩沖區,避免每次從外部媒介中讀取數據,這裡用到了設計模式裡的裝飾器模式,可以參考我之前寫的,

http://www.cnblogs.com/chenpi/p/5173818.html

被裝飾的字符流可以有更多的行為,比如readLine方法等;

舉個使用的例子,讀取外部文件:

package io;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class IOTest {

    public static void main(String[] args) throws IOException  {
        //讀取本地文件,得到字符流,這裡設定緩沖區大小為10k
        BufferedReader reader = new BufferedReader(new FileReader("C:\\test.txt"), 10 * 1024);
        //讀取一行
        System.out.println(reader.readLine());
        System.out.println(reader.readLine());
        System.out.println(reader.readLine());
        //關閉流
        reader.close();
    }
}

LineNumberReader

繼承BufferedReader,除了BufferedReader提供的功能外,還多了獲取行號信息,

注意,LineNumberReader的setLineNumber方法並不能實現流的跳躍讀取

舉個例子

package io;

import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class IOTest {

    public static void main(String[] args) throws IOException  {
        //讀取本地文件,得到字符流,這裡設定緩沖區大小為10k
        LineNumberReader reader = new LineNumberReader(new FileReader("C:\\test.txt"), 10 * 1024);
        
        System.out.println(reader.getLineNumber());//打印當前行號
        System.out.println(reader.readLine());//讀取一行
        System.out.println(reader.getLineNumber());
        System.out.println(reader.readLine());//讀取一行
        //關閉流
        reader.close();
    }
}

FilterReader

抽象類FilterReader是實現自定義過濾輸入字符流的基類,從源碼的實現上來看,僅僅只是簡單覆蓋了Reader中的所有方法,感覺沒什麼卵用,因為已經有一個抽象類Reader了;

PushbackReader

簡單的說,PushbackReader字符流允許你在讀取字符的過程中,通過調用unread方法往緩沖區插入字符,下次讀取的時候,先從緩沖區讀數據,緩沖區沒數據再從流中讀取;

該類同樣使用了裝飾器模式;

一般可以用PushbackReader完成讀取回退功能,比如把之前讀取的字符通過調用unread方法插入到緩沖區中,下次再讀取的時候,就又可以讀取到之前的數據了;

舉個例子如下:

package io;

import java.io.FileReader;
import java.io.IOException;
import java.io.PushbackReader;

public class IOTest {

    public static void main(String[] args) throws IOException {
        // 讀取本地文件,得到字符流,這裡設定緩沖區大小為1024k
        PushbackReader reader = new PushbackReader(new FileReader("C:\\test.txt"), 1024);
        // 讀取一個字符
        char a = (char) reader.read();
        System.out.println(a);
        // 將讀取的字符推回到流中
        // 其實說的簡單點,就是將字符a存到緩沖區中,下次讀取的時候先從緩沖區讀數據,緩沖區沒數據再從流中讀取
        reader.unread(a);
        // 重新讀取之前的字(在緩沖區中)
        System.out.println((char) reader.read());
        // 從流中讀取數據
        System.out.println((char) reader.read());
        // 關閉流
        reader.close();
    }
}

StringReader

將字符串轉為字符輸入流,比較簡單,看個使用例子如下:

package io;

import java.io.IOException;
import java.io.StringReader;

public class IOTest {

    public static void main(String[] args) throws IOException {
        // 通過字符串,得到字符流
        StringReader reader = new StringReader("hello~");
        // 從流中讀取數據
        char[] cbuf = new char[6];
        reader.read(cbuf, 0, 6);
        System.out.println(cbuf);
        // 關閉流
        reader.close();
    }
}
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved