欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java I/O流中的字符流有哪些

 更新時間:2023年10月08日 08:46:38   作者:一一哥Sun  
字節(jié)流的功能已經(jīng)十分強大,幾乎可以直接或間接地處理任何類型的輸入/輸出操作,但它卻不能直接操作16位的Unicode字符,這就需要使用字符流,所以在今天的內(nèi)容中,小編會給大家講解IO流中的字符流,希望各位能夠繼續(xù)耐心學(xué)習

Java中的字符流,可以分為字符輸入流(Reader)和字符輸出流(Writer),輸入流用于讀取數(shù)據(jù),輸出流用于寫入數(shù)據(jù),接下來就讓我們來逐個了解吧。

一. Reader字符輸入流

1. 簡介

Reader是I/O庫中用于讀取字符流的抽象類,它提供了一組方法用于讀取字符流中的字符,并支持不同的字符編碼。

實際上,除了特殊的CharArrayReader和StringReader,普通的Reader本質(zhì)上就是一個帶有編碼轉(zhuǎn)換器的InputStream,它可以把byte轉(zhuǎn)換為char。也就是說,普通的Reader就是基于InputStream構(gòu)造出來的,比如在FileReader的源碼內(nèi)部就有一個FileInputStream對象。而我們也完全可以把一個InputStream轉(zhuǎn)換為Reader,比如:

// InputStream對象
InputStream is = new FileInputStream("a.txt");
// InputStream轉(zhuǎn)為Reader
Reader reader = new InputStreamReader(is, "UTF-8");

在這里,InputStreamReader就是一種用于將字節(jié)流轉(zhuǎn)換為字符流的轉(zhuǎn)換流,使用轉(zhuǎn)換流可以在一定程度上避免亂碼,還可以指定輸入輸出所使用的字符集。其中,InputStreamReader用于將字節(jié)輸入流轉(zhuǎn)換為字符輸入流,OutputStreamWriter用于將字節(jié)輸出流轉(zhuǎn)換為字符輸出流。

Reader和InputStream之間有關(guān)系,當然也有很多區(qū)別,比如:

  • InputStream是一個字節(jié)流,即以byte為單位讀取,讀取的字節(jié)范圍是(-1,0~255),數(shù)據(jù)會讀到字節(jié)數(shù)組中;
  • 而Reader是一個字符流,要以char為單位讀取,讀取的字符范圍是(-1,0~65535),數(shù)據(jù)會讀到字符數(shù)組中。

2. 常用子類

因為Reader是抽象類,所以我們不能直接對其進行實例化,如果我們想使用字符輸入流,需要使用Reader的某個具體子類來實例化對象。Reader的常用子類有如下幾個:

  • InputStreamReader類:將字節(jié)輸入流轉(zhuǎn)換為字符輸入流,可以指定字符編碼;
  • BufferedReader類:為其他字符輸入流提供讀緩沖區(qū);
  • CharArrayReader類:將字符數(shù)組轉(zhuǎn)換為字符輸入流,從中讀取字符;
  • StringReader類:將字符串轉(zhuǎn)換為字符輸入流,從中讀取字符;
  • FileReader類:用于讀取文本文件,并支持不同的字符編碼;
  • PipedReader類:連接到一個PipedWriter。

3. 常用方法

Reader字符流中的常用方法,其實與InputStream中的常用方法基本一致,比如:

方法名及返回值類型說明
int read()從輸入流中讀取一個字符,并把它轉(zhuǎn)換為 0~65535 之間的整數(shù)。如果返回 -1, 則表示已經(jīng)到了輸入流的末尾。該方法不常用。
int read(char[] cbuf)從輸入流中讀取若干個字符,并把它們保存到cbuf參數(shù)指定的字符數(shù)組中。最終返回讀取的字符數(shù),如果返回 -1,則表示已經(jīng)到了輸入流的末尾。
int read(char[] cbuf,int off,int len)從輸入流中讀取若干個字符,并把它們保存到cbuf參數(shù)指定的字符數(shù)組中。off表示字符數(shù)組中開始保存數(shù)據(jù)的起始下標,len表示讀取的字符數(shù)。最后返回實際讀取的字符數(shù),如果返回 -1,則表示已經(jīng)到了輸入流的末尾。

4. 實現(xiàn)步驟

如果我們想使用Reader讀取字符流,可以遵循以下基本步驟:

創(chuàng)建一個Reader對象,比如InputStreamReader、FileReader、StringReader等;

調(diào)用Reader的read()方法來讀取字符流,該方法會返回一個整數(shù),表示讀取的字符數(shù)。如果已到達流的末尾,則read()方法返回-1;

處理讀取的字符,可以將它們存儲在數(shù)組或字符串中;

循環(huán)調(diào)用read()方法,直到讀取完整個字符流。

5. 代碼案例

為了讀取方便,Java給我們提供了用來讀取字符文件的便捷類——FileReader,所以這里利用FileReader讀取了一個文本文件。

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Demo08 {
    public static void main(String[] args) throws FileNotFoundException, IOException {
        // try(resource)的寫法
        //1. 創(chuàng)建Reader對象
        try (FileReader reader = new FileReader("F:/a.txt")) {
            //設(shè)置編碼為UTF-8
            //Reader reader = new FileReader("F:/a.txt", StandardCharsets.UTF_8);
            //2. 讀取文件
            char[] cbuf = new char[1024];
            int len;
            while((len = reader.read(cbuf)) != -1) {
                //3.處理字符
                String str = new String(cbuf, 0, len);
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } //4.自動資源釋放
    }
}

在上面的案例中,read()方法可以一次讀取一個字符數(shù)組,并返回實際讀入的字符個數(shù),最大不會超過char[]數(shù)組的長度,如果讀到流的末尾就返回-1。所以利用這個方法,我們可以先設(shè)置一個緩沖區(qū),然后每次盡可能地填充緩沖區(qū)。

大家可以發(fā)現(xiàn),其實Reader字符流的使用,與InputStream字節(jié)流的使用基本類似。

另外我們在構(gòu)造FileReader對象時,默認的字符編碼及字節(jié)緩沖區(qū)大小都是由系統(tǒng)設(shè)定好的,如果我們想自己指定這些值,可以在FilelnputStream上套接一個InputStreamReader。在上面的代碼中,如果我們讀取的是純ASCII編碼的文本文件,輸出的內(nèi)容不會產(chǎn)生亂碼。但如果文件中包含中文,就會出現(xiàn)亂碼,這就是因為FileReader采用的是操作系統(tǒng)默認的編碼,在Windows中默認的是GBK,而打開UTF-8編碼的文本文件可能就會出現(xiàn)亂碼。所以為了避免讀取中文時產(chǎn)生亂碼,我們可以在創(chuàng)建FileReader時指定編碼:

Reader reader = new FileReader("a.txt", StandardCharsets.UTF_8);

二. Writer字符輸出流

1. 簡介

Writer是I/O庫中用于寫入字符流的抽象類,它提供了一組方法用于將字符寫入到字符流中,并支持不同的字符編碼。除了CharArrayWriter和StringWriter之外,普通的Writer都是基于OutputStream構(gòu)造的。所以本質(zhì)上Writer是一個帶有編碼轉(zhuǎn)換器的OutputStream,可以把char轉(zhuǎn)換為byte并輸出,即接收char,然后在內(nèi)部會自動轉(zhuǎn)換成一個或多個byte,并寫入到OutputStream中。比如我們可以利用OutputStreamWriter,將任意的OutputStream轉(zhuǎn)換為Writer,所以OutputStreamWriter是一種用于將字節(jié)輸出流轉(zhuǎn)換為字符輸出流的轉(zhuǎn)換流

//創(chuàng)建FileOutputStream對象
FileOutputStream fos=new FileOutputStream("readme.txt");
//將FileOutputStream轉(zhuǎn)為Writer
Writer writer = new OutputStreamWriter(fos, "UTF-8")

同樣的,Writer和OutputStream也具有一些區(qū)別:

  • OutputStream是一個字節(jié)流,即以byte為單位讀取,讀取的字節(jié)范圍是0~255;
  • Writer是一個字符流,要以char為單位讀取,讀取的字符范圍是0~65535。

2. 常用子類

Writer是所有字符輸出流的父類,常用的Writer子類有如下這些:

  • OutputStreamReader類:將字節(jié)輸出流轉(zhuǎn)換為字符輸出流,可以指定字符編碼;
  • BufferedWriter類:為其他字符輸出流提供寫緩沖區(qū);
  • CharArrayWriter類:向內(nèi)存緩沖區(qū)的字符數(shù)組寫數(shù)據(jù);
  • StringWriter類:向內(nèi)存緩沖區(qū)的字符串(StringBuffer)寫入數(shù)據(jù);
  • FileReader類:用于寫入文本文件,并支持不同的字符編碼;
  • PipedWriter類:連接到一個PipedReader對象。

3. 常用方法

同樣的,我們也來看看Writer類中的常用方法:

方法名及返回值類型說明
void write(int c)向輸出流中寫入一個字符。
void write(char[] cbuf)把cbuf參數(shù)指定的字符數(shù)組中的所有字符,寫到輸出流中。
void write(char[] cbuf,int off,int len)把cbuf參數(shù)指定的字符數(shù)組中的若干字符寫到輸出流中。off 表示字符數(shù)組的起始下標,len表示元素的個數(shù)。
void write(String str)向輸出流中寫入一個字符串。
void write(String str, int off,int len)向輸出流中寫入一個字符串的部分字符。off表示字符串中的起始偏移量,len表示字符個數(shù)。
append(char c)將參數(shù)c指定的字符添加到輸出流中。
append(charSequence esq)將參數(shù)esq指定的字符序列添加到輸出流中。
append(charSequence esq,int start,int end)將參數(shù)esq指定的字符序列的子序列添加到輸出流中。start表示子序列中的第一個字符索引,end表示子序列中最后一個字符后面的字符索引。即子序列的內(nèi)容包含start索引處的字符,但不包括end索引處的字符。

大家要注意:Writer類中所有的方法在出錯時都會引發(fā)IOException異常,如果我們關(guān)閉一個流后再對其進行任何操作,都會產(chǎn)生錯誤。

4. 代碼案例

我們設(shè)計一個FileWriter的使用案例,代碼如下:

import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class Demo09 {
	public static void main(String[] args) throws FileNotFoundException, IOException {
		// try(resource)的寫法
		// 1. 創(chuàng)建Writer對象
		try (FileWriter writer = new FileWriter("F:/b.txt")) {
			// 利用Scanner進行內(nèi)容的輸入
			Scanner input = new Scanner(System.in);
			// 2. 寫入文件
			for (int i = 0; i < 5; i++) {
				System.out.println("請輸入第" + (i + 1) + "行內(nèi)容:");
				// 讀取輸入的名稱
				String content = input.next(); 
				// 循環(huán)寫入到文件中
				writer.write(content + "\r\n"); 
                //writer.append(“追加新內(nèi)容...”);
			}
			System.out.println("錄入完畢");
			input.close();
		} catch (IOException e) {
			e.printStackTrace();
		} // 3.自動資源釋放
	}
}

FileWriter是向文件中寫入字符流的Writer,它的使用和FileReader類似。這里的FileWriter對象直接關(guān)聯(lián)了一個文件,然后我們可以調(diào)用write()或append()方法進行內(nèi)容的新增和追加了。我們在創(chuàng)建FileWriter對象時,默認的字符編碼和字節(jié)緩沖區(qū)的大小都是由系統(tǒng)設(shè)定的。如果我們想要自己指定這些值,可以在FileOutputStream上套接一個OutputStreamWriter對象。

在創(chuàng)建FileWriter類對象時,如果關(guān)聯(lián)的文件不存在,則會自動生成一個新的文件。在創(chuàng)建文件之前,F(xiàn)ileWriter會在創(chuàng)建對象時打開該文件作為輸出目的地,但如果試圖打開的是一個只讀文件,會引發(fā)IOException異常。

三. 字符緩沖流

1. 簡介

與字節(jié)緩沖流類似,我們在進行大文件讀寫操作時,也可以使用字符緩沖流來減少訪問磁盤的次數(shù),提高IO訪問效率。Java中的字符緩沖流包括BufferedReader和BufferedWriter兩大類,分別負責文件的讀取和寫入。

2. 常用子類

Java中的字符緩沖流可以分為緩沖的字符輸入流BufferedReader和緩沖的字符輸出流BufferedWriter。

  • BufferedReader:繼承自InputStreamReader 類, 用于讀取二進制數(shù)據(jù),并將數(shù)據(jù)存儲在內(nèi)部緩沖區(qū)中;
  • BufferedWriter:繼承自OutputStreamWriter類,用于寫入二進制數(shù)據(jù),并將數(shù)據(jù)存儲在內(nèi)部緩沖區(qū)中。

3. BufferedReader的用法

BufferedReader是一個帶有緩沖區(qū)的輸入流,主要用于輔助其他的字符輸入流。BufferedReader可以先將一批數(shù)據(jù)讀到內(nèi)存緩沖區(qū),然后接下來的讀操作就可以直接從該緩沖區(qū)中獲取數(shù)據(jù),并進行字符編碼轉(zhuǎn)換,這樣就可以提高數(shù)據(jù)的讀取效率。

另外BufferedReader還提供了一個readLine()方法,該方法會返回包含所讀內(nèi)容的字符串,但該字符串中不包含任何終止符,如果已到達了流的末尾,就返回null。readLine()方法表示每次讀取一行的文本內(nèi)容,當遇到換行(\n)、回車(\r)或回車后直接跟著換行標記符,即認為某行終止。接下來我們就來看看BufferedReader是怎么使用的吧。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Demo11 {
	public static void main(String[] args) throws FileNotFoundException, IOException {
		// try(resource)的寫法
		// 1. 創(chuàng)建Reader對象
		try(BufferedReader reader=new BufferedReader(new FileReader("F:\a.txt"))) {
            String strLine = "";
            while ((strLine = reader.readLine()) != null) { 
                //循環(huán)讀取每行數(shù)據(jù)
                System.out.println(strLine);
            }
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }  // 3.自動資源釋放
	}
}

4. BufferedWriter的用法

BufferedWriter則是一個帶有緩沖區(qū)的輸出流,主要用于輔助其他的字符輸出流。BufferedWriter同樣帶有緩沖區(qū),可以先將一批數(shù)據(jù)寫入到緩沖區(qū),當緩沖區(qū)滿了以后,再將緩沖區(qū)里的數(shù)據(jù)一次性寫到字符輸出流,這樣也提高了數(shù)據(jù)的寫入效率。

BufferedWriter類中提供了一個新的方法newLine(),該方法用于寫入一個行分隔符。行分隔符字符串由系統(tǒng)屬性 line.separator定義,且不一定是單個新行(\n)符。BufferedWriter類的用法如下:

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
public class Demo12 {
	public static void main(String[] args) throws FileNotFoundException, IOException {
		// try(resource)的寫法
		// 1. 創(chuàng)建Writer對象
		try (BufferedWriter writer = new BufferedWriter(new FileWriter("F:/c.txt"))) {
			//2.寫入內(nèi)容
			writer.write("Hello, world!");
			//3.換行
			writer.newLine();
			writer.write("Welcome to learn Java!");
			// writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

在上面的代碼中,我們使用了BufferedWriter類來寫入字符流,使用newLine()方法添加一個新行,在寫入完成后可以關(guān)閉寫入器對象。

5. 綜合案例

在學(xué)習了上面的字符輸入流、字符輸出流、轉(zhuǎn)換流以及緩沖流等內(nèi)容之后,最后給大家設(shè)計一個綜合案例,來把這幾個知識點糅合在一起。

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
public class Demo13 {
	public static void main(String[] args) throws FileNotFoundException, IOException {
		try {
	        //將System.in對象轉(zhuǎn)換成InputStreamReader對象
	        InputStreamReader reader = new InputStreamReader(System.in);
	        // 將Reader對象包裝成BufferedReader
	        BufferedReader br = new BufferedReader(reader);
	        String line = null;
	        //利用循環(huán)方式逐行讀取
	        while ((line = br.readLine()) != null) {
	            // 如果讀取到“exit”,則程序退出
	            if (line.equals("exit")) {
                    //退出程序
	                System.exit(1);
	            }
	            // 打印出讀取到的內(nèi)容
	            System.out.println("輸入的內(nèi)容為:" + line);
	        }
	    } catch (IOException e) {
	        e.printStackTrace();
	    }
	}
}

在上面的案例中,我們使用了System.in獲取到鍵盤的輸入信息,該信息其實是InputStream的實例。但該實例使用不太方便,我們使用 InputStreamReader 將其轉(zhuǎn)換成字符輸入流,因為Reader讀取輸入內(nèi)容時依然不太方便,我們繼續(xù)把Reader包裝成BufferedReader。因為BufferReader具有readLine()方法,可以非常方便地一次讀入一行內(nèi)容。而且BufferReader具有緩沖功能,一次讀取一行文本,以換行符為標志,如果它沒有讀到換行符,則程序堵塞,等到讀到換行符為止。運行該程序后,在控制臺執(zhí)行輸入時,只要按下回車鍵,程序就會打印出剛剛輸入的內(nèi)容。

四. 結(jié)語

到此這篇關(guān)于詳解Java I/O流中的字符流有哪些的文章就介紹到這了,更多相關(guān)Java字符流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot配置主從數(shù)據(jù)庫實現(xiàn)讀寫分離

    SpringBoot配置主從數(shù)據(jù)庫實現(xiàn)讀寫分離

    現(xiàn)在的 Web 應(yīng)用大都是讀多寫少,本文主要介紹了SpringBoot配置主從數(shù)據(jù)庫實現(xiàn)讀寫分離,具有一定的參考價值,感興趣的可以了解一下
    2023-11-11
  • 在CentOS上配置Java環(huán)境變量的教程

    在CentOS上配置Java環(huán)境變量的教程

    這篇文章主要介紹了在CentOS上配置Java環(huán)境變量的教程,同時適用于Fedora等其他RedHat系的Linux系統(tǒng),需要的朋友可以參考下
    2015-06-06
  • 編寫Java代碼制造一個內(nèi)存溢出的情況

    編寫Java代碼制造一個內(nèi)存溢出的情況

    這篇文章主要介紹了編寫Java代碼制造一個內(nèi)存溢出的情況,或許這種有意制造能夠更好地幫助理解Java中的內(nèi)存溢出情況XD 需要的朋友可以參考下
    2015-07-07
  • 使用Apache Spark進行Java數(shù)據(jù)分析的步驟詳解

    使用Apache Spark進行Java數(shù)據(jù)分析的步驟詳解

    今天我們將探討如何使用Apache Spark進行Java數(shù)據(jù)分析,Apache Spark是一個強大的大數(shù)據(jù)處理引擎,它支持批處理和流處理,特別適合處理大規(guī)模數(shù)據(jù)集,在Java中使用Spark,我們可以利用其強大的數(shù)據(jù)處理能力來進行各種數(shù)據(jù)分析任務(wù),需要的朋友可以參考下
    2024-07-07
  • Spring 3.x中三種Bean配置方式比較詳解

    Spring 3.x中三種Bean配置方式比較詳解

    這篇文章主要介紹了Spring 3.x中三種Bean配置方式比較詳解,具有一定借鑒價值,需要的朋友可以參考下
    2017-12-12
  • java開發(fā)微信分享接口的步驟

    java開發(fā)微信分享接口的步驟

    這篇文章主要為大家詳細介紹了java開發(fā)微信分享接口的步驟,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Java 數(shù)據(jù)結(jié)構(gòu)算法Collection接口迭代器示例詳解

    Java 數(shù)據(jù)結(jié)構(gòu)算法Collection接口迭代器示例詳解

    這篇文章主要為大家介紹了Java 數(shù)據(jù)結(jié)構(gòu)算法Collection接口迭代器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Java編程中的一些常見問題匯總

    Java編程中的一些常見問題匯總

    這篇文章主要介紹了Java編程中的一些常見問題匯總,本文總結(jié)的都是一些Java代碼中比較典型的錯誤,需要的朋友可以參考下
    2014-09-09
  • Java中枚舉的實現(xiàn)與應(yīng)用詳解

    Java中枚舉的實現(xiàn)與應(yīng)用詳解

    這篇文章主要介紹了Java中枚舉的實現(xiàn)與應(yīng)用詳解,EnumTest中還有一個VALUES數(shù)組,里面存儲著所有的枚舉實例,調(diào)用values方法時返回VALUES數(shù)組的clone,需要的朋友可以參考下
    2023-12-12
  • Java應(yīng)用程序的CPU使用率飆升原因詳細分析

    Java應(yīng)用程序的CPU使用率飆升原因詳細分析

    這篇文章主要介紹了Java應(yīng)用程序的CPU使用率飆升原因詳細分析,在 Java 中,我們使用 JVM 進行線程調(diào)度,所以一般來說,線程的調(diào)度有兩種模式:分時調(diào)度和搶占式調(diào)度,線程和進程在阻塞或者等待時,都不會使用 CPU 資源,需要的朋友可以參考下
    2024-01-01

最新評論