天天看點

java IO程式設計(二)位元組流與字元流

在java中對資料流的操作分為輸入與輸出兩種方式,而且針對此操作提供了一下兩類支援。

  • 位元組流(JDK 1.0開始提供):InputStream(輸入位元組流)、OutputStream(輸出位元組流); 
  • 字元流(JDK 1.1開始提供):Reader(輸入字元流)、Writer(輸出字元流)。

一、位元組流

輸出位元組流 OutputStream

OutputStream類的常用方法

No. 方法 類型 描述
1 public void close() throws IOException 普通 關閉位元組流
2 public void flush() throws IOException 普通 強制重新整理
3 public abstract void write(int b) thorws IOException 普通 輸出單個位元組
4 public void write(byte[] b) throws IOException 普通 輸出全部位元組數組資料
5 public void write(byte[] b,int off,int len) throws IOExcption 普通 輸出部分位元組數組資料

注:OutputStream類是個抽象類,同時實作了Closeable和Flushable接口,而Closeable繼承了AutoCloseable接口,是以當使用完OutputStream後即使不手動關閉資源,系統也會自動将資源關閉

OutputStream類本身是一個抽象類,如果需要進行檔案操作,可以使用FileOutputStream子類完成。 

FileOutputStream類的常用方法

No. 方法 類型 描述
1 public FileOutputStream(File file) throws FileNotFoundException 構造 将内容輸出到指定路徑,如果檔案已存在則使用新的内容覆寫舊的内容
2 public FileOutputStream(File file,boolean append) throws FileNotFoundException 構造 如果将布爾參數設定為true,則表示追加新的内容到檔案中

1.使用位元組輸出流将設定好的内容輸出到指定檔案中

package com.tjut.streamTest;

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

public class StreamTest01 {
	
	public static void main(String[] args) throws IOException {
		//定義要輸出檔案的路徑
		File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
		//此時由于目錄不存在,是以檔案不能輸出,應該首先建立目錄
		if(!file.getParentFile().exists()) {
			file.getParentFile().mkdirs();
		}
		//利用OutputStream向檔案輸出資訊時如果檔案不存在,則會自動建立(不需要使用者手動調用createNewFile()方法)
		OutputStream output = new FileOutputStream(file);
		String str = "沒有月色的夜裡,螢火蟲用心點亮漫天的星";
		byte[] data = str.getBytes();
		output.write(data);
		output.close();
	}
	


}
           

讀者可以嘗試使用單個位元組的方式輸出

for(int i = 0;i < data.length;i++) {
			output.write(data[i]);
		}
           

 或者輸出部分位元組數組的内容

output.write(data,6,6);
           

輸入位元組流 InputStream

InputStream的可以對比OutputStream來學習,同樣是抽象類,也不需要手動關閉資源。

InputStream類的常用方法

No. 方法 類型 描述
1 public void close() throws IOException 普通 關閉位元組輸入流
2 public abstract int read() throws IOException 普通 讀取單個位元組
3 public int read(byte[] b) throws IOException 普通 将資料讀取到位元組數組中,同時傳回讀取的資料長度
4 public int read(byte[] b,int off,int len) throws IOException 普通 将資料讀取到部分位元組數組中,同時傳回讀取的資料長度

注:read()方法讀到結尾後會傳回-1

 InputStream本身是一個抽象類,需要使用FileInputStream類來實作相應的檔案操作

FileInputStream類的常用方法

No. 方法 類型 描述
1 public FileInputStream(File file) throws FileNotFoundException 普通 設定要讀取檔案資料的路徑

 2.使用位元組輸入流讀取指定檔案中的資料,并将其輸出到控制台

package com.tjut.streamTest;

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

public class StreamTest02 {
	
	public static void main(String[] args) throws IOException {
		//1.定義要輸入檔案的路徑
		File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
		if(file.exists()) {//判斷檔案是否存在
			//2.使用InputStream進行讀取
			InputStream input = new FileInputStream(file);
			byte[] data = new byte[1024];//準備一個1024的位元組數組
			int len = input.read(data);//3.進行資料讀取,将内容儲存到位元組數組中
			input.close();//4.關閉輸入流
			System.out.println(new String(data,0,len));
		}
	}

}
           

 你也可以嘗試使用while循環,每次讀取一個位元組

int foot = 0;
			int temp = 0;
			while((temp = input.read()) != -1) {
				data[foot++] = (byte)temp;
			}
           

二、字元流 

字元輸出流Writer

        Writer是一個抽象類,實作了Appendable、Closeable(父接口AutoCloseable)和Flushable接口,是以也不需要手動關閉資源。利用Writer類可以實作字元數組(包含了字元串)的輸出

Writer類的常用方法

No. 方法 類型 描述
1 public void close() throws IOException 普通 關閉字元輸出流
2 public void flush() throws IOException 普通 強制重新整理
3 public Writer append(CharSequence csq) throws IOException 普通 追加資料
4 public void write(String str) throws IOException 普通 輸出字元串資料
5 public void write(char[] cbuf) throws IOException 普通 輸出字元數組資料

Writer是一個抽象類,要針對檔案内容進行輸出,可以使用java.io.FileWriter類實作Writer類對象的執行個體化操作。

No. 方法 類型 描述
1 public FileWriter(File file) throws IOException 構造 設定輸出檔案
2 public FileWriter(File file,boolean append) throws IOException 構造 設定輸出檔案以及是否進行資料追加

 3.使用字元輸出流将特定内容寫入指定檔案中

package com.tjut.streamTest;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class StreamTest03 {
	public static void main(String[] args) throws IOException {
		//1.定義要輸入檔案的路徑
		File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
		if(!file.getParentFile().exists()) {//判斷目錄是否存在
			file.getParentFile().mkdirs();//建立檔案目錄
		}
		
		Writer write = new FileWriter(file);//2.執行個體化Writer對象
		String str = "美麗的夢和美麗的詩一樣 \r\n" + "都是可遇而不可求的 \r\n" + 
				"常常在最沒能料到的時刻裡出現";
		write.write(str);//3.輸出字元串資料
		write.close();//4.關閉輸出流
	}
}
           

字元輸入流Reader

        java.io.Reader類是實作字元資料輸入的操作類,在進行資料讀取時可以不使用位元組資料,而直接依靠字元資料(友善進行中文)進行操作。 

Reader類的常用方法

No. 方法 類型 描述
1 public void close() throws IOException 普通 關閉字元輸入流
2 public int read() throws IOException 普通 讀取單個字元
3 public int read(char[] cbuf) throws IOException  普通 讀取字元到字元數組中,傳回讀取長度
4 public long skip(long n) throws IOException 普通 跳過位元組長度

注:Reader類實作了Closeable(父接口為AutoCloseable)和Readable接口,是以不需要手動關閉資源

        Writer類中存在直接輸出字元串的操作,而Reader類中并沒有直接傳回字元串的操作,這是因為輸出資料時可以采用追加模式,導緻檔案變得非常龐大。如果在Reader類中提供了直接讀取全部資料的方式,就有可能造成記憶體溢出問題。

        Reader類是一個抽象類,要實作檔案資料的字元流讀取,可以利用FileReader子類為Reader對象執行個體化。

FileReader類的常用方法

No. 方法 類型 描述
1 public FileReader(File file) throws FileNotFoundException 構造 定義要讀取的檔案路徑

4.使用Reader從指定檔案中讀取資料

package com.tjut.streamTest;

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

public class StreamTest04 {
public static void main(String[] args) throws IOException {
	//1.定義要輸入檔案的路徑
	File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
	if(file.exists()) {
		Reader reader = new FileReader(file);//2.為Reader類對象執行個體化
		char[] data = new char[1024];
		int len = reader.read(data);//3.進行資料讀取
		reader.close();//4.關閉輸入流
		System.out.println(new String(data,0,len));
	}
}
}
           

位元組流與字元流的差別

        位元組流直接與終端檔案進行資料互動,字元流需要将資料經過緩沖區處理才與終端檔案資料互動。在使用OutputStream輸出資料時即使最後沒有關閉輸出流,内容也可以正常輸出,但是反過來如果使用的是字元輸出流Writer,在執行到最後如果不關閉輸出流,就表示在緩沖區中處理的内容不會被強制性清空,是以就不會輸出資料。如果有特殊情況不能關閉字元輸出流,可以使用flush()方法強制清空緩沖區。

5.強制清空字元流緩沖區

package com.tjut.streamTest;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class StreamTest05 {
	
	public static void main(String[] args) throws IOException {
		//1.定義要輸出檔案的路徑
		File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
		if(!file.getParentFile().exists()) {//判斷目錄是否存在
			file.getParentFile().mkdirs();//建立檔案目錄
		}
		
		Writer writer = new FileWriter(file);//2.執行個體化Writer類對象
		String str = "我喜歡那樣的夢 \r\n" + 
				"在夢裡 一切都可以重新開始 \r\n" + 
				"一切都可以慢慢解釋 \r\n" + 
				"心裡甚至還能感覺到所有被浪費的時光 \r\n" + 
				"竟然都能重回時的狂喜和感激";
		writer.write(str);//3.輸出字元串資料
		writer.flush();//強制重新整理緩沖區
	}

}
           

注:在開發中,如果要進行中文時應優先考慮字元流,如果沒有中文問題,建議使用位元組流。

三、轉換流 

        雖然位元組流和字元流表示兩種不同的資料流操作,但是這兩種流彼此間是可以實作互相轉化的,雖然轉換流的使用情況并不多。

轉換流用到的方法

名稱 InputStreamReader OutputStreamReader
定義結構 public class InputStreamReader extends Reader public class OutputStreamWriter extends Writer
構造方法 public InputStreamReader(InputStream in) public OutputStreamWriter(OutputStream out)

6.将位元組輸出流(OutputStream)轉換為字元輸出流(Writer)

package com.tjut.streamTest;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class StreamTest06 {
	
	public static void main(String[] args) throws IOException {
		//1.定義要輸出檔案的路徑
		File file = new File("d:" + File.separator + "Demo" + File.separator + "Hello" + File.separator + "test.txt");
		if(!file.getParentFile().exists()) {//判斷目錄是否存在
			file.getParentFile().mkdirs();//建立目錄
		}
		OutputStream output = new FileOutputStream(file);//位元組流
		//将OutputStream類對象傳遞給OutputStreamWriter類的構造方法,而後向上轉型為Writer
		Writer writer = new OutputStreamWriter(output);
		String str = "胸懷中滿溢著幸福\r\n" + 
				"隻因為你就在我眼前\r\n" + 
				"對我微笑 一如當年\r\n" + 
				"我真喜歡那樣的夢";
		writer.write(str);//Writer類的方法
		writer.flush();
		writer.close();
	}

}
           

 檔案操作類的繼承結構如下:

java IO程式設計(二)位元組流與字元流

        通過繼承結構可以發現,FileWriter與FileReader都是轉換流的子類,也就證明所有要讀取的檔案資料都是位元組資料,所有 的字元都是在記憶體中處理後形成的。