Java總結:Java 流(Stream)、文件(File)和IO


更新時間:2018-1-7 12:27:21

更多請查看在線文集:http://android.52fhy.com/java/index.html


java.io 包幾乎包含了所有操作輸入、輸出需要的類。所有這些流類代表了輸入源和輸出目標。

輸入輸出流

簡介

一個流被定義為一個數據序列。輸入流用於從源讀取數據,輸出流用於向目標寫數據。

下圖是一個描述輸入流和輸出流的類層次圖:

java.io包中操作文件內容的主要有兩大類:字節流、字符流,兩類都分為輸入和輸出操作。

在字節流中輸出數據主要是使用OutputStream完成,輸入使的是InputStream;在字符流中輸出主要是使用Writer類完成,輸入流主要使用Reader類完成。這四個都是抽象類。

java中提供了專用於輸入輸出功能的包java.io, 其中包括:

  • InputStream, OutputStream, Reader, Writer
  • InputStreamOutputStream, 兩個是為字節流設計的,主要用來處理字節或二進制對象。
  • ReaderWriter, 兩個是為字符流(1個字符占2個字節)設計的,主要用來處理字符或字符串。

常見的System.in其實就是InputStream對象。

字節流轉換為字符流

為了方便處理字節流,我們經常會把字節流轉換為字符流。例如:

Java 的控制台輸入由 System.in 完成。為了獲得一個綁定到控制台的字符流,我們可以把 System.in 包裝在一個 BufferedReader 對象中來創建一個字符流。

下面是創建 BufferedReader 的基本語法:

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

同理,從文件讀取:

InputStream f = new FileInputStream("C:/java/hello");
BufferedReader br = new BufferedReader(new InputStreamReader(f));

使用BufferedReader是為了使用緩沖功能。

java.io.BufferedReaderjava.io.BufferedWriter類各擁有8192字符的緩沖區。當BufferedReader在讀取文本文件時,會先盡量從文件中讀入字符數據並置入緩沖區,而之后若使用read()方法,會先從緩沖區中進行讀取。如果緩沖區數據不足,才會再從文件中讀取,使用BufferedWriter時,寫入的數據並不會先輸出到目的地,而是先存儲至緩沖區中。如果緩沖區中的數據滿了,才會一次對目的地進行寫出。

針對上面示例的三個類進行簡單說明:

  • InputStream:是所有字節輸入流的超類,一般使用它的子類:FileInputStream等,它能輸出字節流;
  • InputStreamReader:是字節流與字符流之間的橋梁,能將字節流輸出為字符流,並且能為字節流指定字符集,可輸出一個個的字符;
  • BufferedReader:提供通用的緩沖方式文本讀取,readLine()讀取一個文本行,從字符輸入流中讀取文本,緩沖各個字符,從而提供字符、數組和行的高效讀取。

InputStream提供的read()方法支持從輸入流中讀取一個數據字節。常用原型:

public int read() throws IOException {}

從此輸入流中讀取一個數據字節。如果沒有輸入可用,則此方法將阻塞。
指定者:類 InputStream 中的 read
返回:下一個數據字節;如果已到達文件末尾,則返回 -1。

public int read(byte[] b) throws IOException{}

從此輸入流中將最多 b.length 個字節的數據讀入一個 byte 數組中。在某些輸入可用之前,此方法將阻塞。
覆蓋:類 InputStream 中的 read
參數:存儲讀取數據的緩沖區。
返回:讀入緩沖區的字節總數,如果因為已經到達文件末尾而沒有更多的數據,則返回 -1。

示例

示例1:從控制台讀取單字符輸入

public static void main(String[] args) throws IOException{
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	char c;
	
	System.out.println("輸入字符,按下 'q' 鍵退出:");
	
	do {
		c = (char) br.read();
		System.out.println(c);
	}while(c != 'q');
}

示例2:從控制台讀取多字符輸入

public static void main(String[] args) throws IOException{
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	String s;
	System.out.println("輸入字符串,按下 'quit' 鍵退出:");
	
	do {
		s = br.readLine();
		System.out.println(s);
	}while(!s.equals("quit"));
}

示例3:使用 InputStream 中的 read讀取字節流

public static void main(String[] args) throws IOException{
	InputStream input = System.in;
	byte[] b = new byte[1024];
	int len = 0;
	StringBuffer sb = new StringBuffer("");

	while ((len = input.read(b)) != 2) {
		System.out.println(len);
		sb.append(new String(b, 0, len));
	}
	
	input.close();
	System.out.println(sb.toString());
}

其實該例子改成文件讀取會更好:

public static void main(String[] args) throws IOException{
	InputStream input = new FileInputStream("src/test.txt");
	byte[] b = new byte[1024];
	int len = 0;
	StringBuffer sb = new StringBuffer("");

	while ((len = input.read(b)) > 0) {
		System.out.println(len);
		sb.append(new String(b, 0, len));
	}
	
	input.close();
	System.out.println(sb.toString());
}

也可以使用一個文件對象來創建一個輸入流對象來讀取文件。我們首先得使用 File() 方法來創建一個文件對象:

File f = new File("src/test.txt");
InputStream input = new FileInputStream(f);

必須先在src目錄下建立文件test.txt,內容: hello world
運行結果:

11
hello world

示例4:控制台輸出:

我們知道,控制台的輸出由 print()println() 完成。這些方法都由類 PrintStream 定義,System.out 是該類對象的一個引用。
PrintStream 繼承了 OutputStream類,並且實現了方法 write()。這樣,write() 也可以用來往控制台寫操作。
但是write() 方法不經常使用,因為 print()println() 方法用起來更為方便。

PrintStream 定義 write() 的最簡單格式如下所示:

void write(int byteval){}

該方法將 byteval 的低八位字節寫到流中。

public static void main(String[] args) {
	System.out.write('h');
	System.out.write('\n');
}

示例5:輸出內容到文件

public static void main(String[] args) throws IOException{
		
	String str = "hello world";
	
	// 構建FileOutputStream對象,文件不存在會自動新建
	OutputStream out = new FileOutputStream("src/test2.txt");
	out.write(str.getBytes());
	out.close();
}

也可以使用一個文件對象來創建一個輸出流來寫文件。我們首先得使用File()方法來創建一個文件對象:

File f = new File("src/test2.txt");
OutputStream out = new FileOutputStream(f);

運行后,打開src目,就能看到test2.txt。

getBytes()用於把字符串轉化為字節流(byte型)。方法原型:

public byte[] getBytes() {
	return StringCoding.encode(value, 0, value.length);
}

public byte[] getBytes(Charset charset) {
	if (charset == null) throw new NullPointerException();
	return StringCoding.encode(charset, value, 0, value.length);
}

示例6:借助BufferedWriter輸出內容到文件

public static void main(String[] args) throws IOException{
		
	String str = "hello";
	
	// 構建FileOutputStream對象,文件不存在會自動新建
	OutputStream out = new FileOutputStream("src/test3.txt");
	BufferedWriter bWriter = new BufferedWriter(new OutputStreamWriter(out));
    bWriter.write(str);
	bWriter.close();//關閉緩沖區
}

我們還可以結合上述的BufferedReader進行從鍵盤輸入,保存到文件:

public static void main(String[] args) throws IOException{
		
	String str = "";
	
	// 構建FileOutputStream對象,文件不存在會自動新建
	OutputStream out = new FileOutputStream("src/test3.txt");
	BufferedWriter bWriter = new BufferedWriter(new OutputStreamWriter(out, "utf-8"));//構建OutputStreamWriter對象,參數可以指定編碼,默認為操作系統默認編碼,windows上是gbk
//		bWriter.write(str);
	
	//讀緩存區
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	
	do {
		str = br.readLine();
		bWriter.write(str);
		System.out.println(str);
	}while(!str.equals("quit"));
	
	bWriter.close();//關閉緩沖區,同時會把緩沖區內容寫入文件
	out.close();// 關閉輸出流,釋放系統資源
}

文件和I/O

主要有這些類:

  • File 文件類。
  • FileReader FileReader類從InputStreamReader類繼承而來。該類按字符讀取流中數據。
  • FileWriter FileWriter 類從 OutputStreamWriter 類繼承而來。該類按字符向流中寫入數據。

File 類至少有一個參數。File 類方法:

  • mkdir()方法創建一個文件夾,成功則返回true,失敗則返回false。
    失敗表明File對象指定的路徑已經存在,或者由於整個路徑還不存在,該文件夾不能被創建。
  • mkdirs()創建指定的目錄,包括創建必需但不存在的父目錄。創建多級目錄使用該方法。
  • isDirectory()判斷是否是一個目錄。
  • isFile() 判斷是否是一個標准文件。
  • list() 提取包含的文件和文件夾的列表。
  • delete()方法同於刪除文件或空目錄。
  • createNewFile() throws IOException
    當且僅當不存在具有此抽象路徑名指定的名稱的文件時,原子地創建由此抽象路徑名指定的一個新的空文件。

示例1:目錄操作

public static void main(String[] args) throws IOException {
	String dirname = "src/tmp";
	File file = new File(dirname);
	
	//創建目錄
	if(!file.isDirectory()) {
		if(file.mkdirs()) {
			System.out.println("succ mkdirs");
		}
	}
	
	//創建文件
	File file2 = new File(dirname + "/test.txt");
	file2.createNewFile();//目錄必須存在
	
	File file3 = new File(dirname + "/test/");
	file3.mkdir();
	
	//列出目錄
	if(file.isDirectory()) {
		String[] lists = file.list();
		for (int i = 0; i < lists.length; i++) {
			File f = new File(dirname + "/" + lists[i]);
			if(f.isDirectory()) {
				System.out.println("[d]"+ lists[i]);
			}else {
				System.out.println("[f]"+ lists[i]);
			}
		}
	}else {
		System.out.println(dirname + " 不是一個目錄");
	}
	
	//刪除文件或目錄
	if(file3.delete()) {
		System.out.println("刪除成功");
	}
}

運行結果:

[d]test
[f]test.txt
刪除成功

示例2:

public static void main(String[] args) throws IOException {
	String filename = "src/tmp/test.txt";
	File file = new File(filename);
	file.createNewFile();// 創建文件
	FileWriter fWriter = new FileWriter(file);//創建FileWriter對象
	fWriter.write('i');
	fWriter.write(' ');
	char[] cs = {'l', 'o', 'v', 'e', ' '};
	fWriter.write(cs);
	fWriter.write("java");
	fWriter.flush();//將輸入流和輸出流中的緩沖進行刷新,使緩沖區中的元素即時做輸入和輸出,而不必等緩沖區滿
	fWriter.close();//關閉FileWriter對象
	
	//讀取文件
	FileReader fReader = new FileReader(file);
	char[] cs2 = new char[15];
	fReader.read(cs2);//這里因為知道長度不會大於15,所以沒有用while循環讀取
	for(char c : cs2) {//遍歷輸出
		System.out.print(c);
	}
	fReader.close();

運行結果:

i love java

參考

1、Java 流(Stream)、文件(File)和IO | 菜鳥教程
http://www.runoob.com/java/java-files-io.html
2、java中char和byte的轉換 - CSDN博客
http://blog.csdn.net/feixiazhitian/article/details/49511963
3、字節流與字符流的區別及相互轉換 - 傑-維斯布魯克 - 博客園
https://www.cnblogs.com/sjjsh/p/5269781.html
4、Java中,BufferedReader類的介紹及作用 - CSDN博客
http://blog.csdn.net/wiebin36/article/details/51912794


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM