Java開發筆記(八十九)緩存字節I/O流

文件輸出流FileOutputStream跟FileWriter一樣有個毛病,每次調用write方法都會直接寫到磁盤,使得頻繁的寫操做性能極其低下。正如FileWriter搭上了緩存兄弟BufferedWriter那樣,FileOutputStream也有本身的緩存兄弟BufferedOutputStream,這個緩存輸出流的用法與緩存寫入器很是類似,主要體如今以下三點:
一、每次建立緩存輸出流對象以前,都要先構建文件輸出流對象,而後據此構建緩存輸出流對象;
二、它的write方法先把數據寫到緩存,等到緩存滿了才寫入磁盤,或者在調用close方法關閉文件之時將緩存數據寫入磁盤。
三、緩存輸出流仍然提供了flush方法,調用flush方法表示當即把緩存中的數據寫入磁盤。
下面是利用緩存輸出流寫文件的代碼例子:html

	private static String mSrcName = "D:/test/aaf.txt";
	// 利用緩存輸出流寫入文件
	private static void writeBuffer() {
		String str = "白日依山盡,黃河入海流。\n欲窮千里目,更上一層樓。";
		// 根據指定文件路徑構建文件輸出流對象,而後據此構建緩存輸出流對象
		try (FileOutputStream fos = new FileOutputStream(mSrcName);
				BufferedOutputStream bos = new BufferedOutputStream(fos)) {
			bos.write(str.getBytes()); // 把字節數組寫入緩存輸出流
			//bos.flush(); // 當即寫入磁盤。若是不當即寫入,最後調用close方法時也會寫入
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

 

看過了緩存輸出流,再來看緩存輸入流BufferedInputStream。因爲字節流操做的數據形式爲字節數組,所以無論是緩存輸出流仍是緩存輸出流,都不提供按行讀寫的功能。若想建立緩存輸入流對象,依舊要先構建文件輸入流對象,再據此構建緩存輸入流對象。另外BufferedInputStream保留了mark和reset兩個方法,前者用於在當前位置作個標記,後者可重置輸入流指針,令其回到上次標記的位置。下面是利用緩存輸入流讀文件的代碼例子:數組

	// 利用緩存輸入流讀取文件
	private static void readBuffer() {
		// 根據指定文件路徑構建文件輸入流對象,而後據此構建緩存輸入流對象
		try (FileInputStream fis = new FileInputStream(mSrcName);
				BufferedInputStream bis = new BufferedInputStream(fis)) {
			// 分配長度爲文件大小的字節數組。available方法返回當前位置後面的剩餘部分大小
			byte[] bytes = new byte[bis.available()];
			bis.read(bytes); // 從緩存輸入流中讀取字節數組
			// 緩存輸入流的mark和reset用法相似於BufferedReader的同名方法
			//bis.mark(bis.available()); // 在當前位置作個標記
			//bis.reset(); // 重置輸入流指針,令其回到上次標記的位置
			String content = new String(bytes); // 把字節數組轉換爲字符串
			System.out.println("content="+content);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

 

由於字節流只處理字節數組,不處理字符數組,因此藉助於字節數組能夠很輕鬆地在輸入和輸出流之間轉換。調用緩存輸入流對象的read方法,將文件數據讀到指定的字節數組;而後調用緩存輸出流對象的write方法,立刻把剛讀取的字節數組寫入文件,一進一出之間就順帶完成了文件複製功能。下面是經過緩存輸入和輸出流複製文件的代碼例子:緩存

	private static String mSrcName = "D:/test/aaf.txt";
	private static String mDestName = "D:/test/aaf_copy.txt";
	// 利用緩存輸入和輸出流複製文件
	private static void copyFile() {
		// 分別構建緩存輸入流對象和緩存輸出流對象
		try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(mSrcName));
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(mDestName))) {
			// 分配長度爲文件大小的字節數組。available方法返回當前位置後面的剩餘部分大小
			byte[] bytes = new byte[bis.available()];
			bis.read(bytes); // 從緩存輸入流中讀取字節數組
			bos.write(bytes); // 把字節數組寫入緩存輸出流
			System.out.println("文件複製完成,源文件大小="+bytes.length+",新文件大小="+bytes.length);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

 

同以前介紹的經過緩存讀取器和寫入器複製文件相比,緩存輸入和輸出流在複製文件的時候去掉了惱人的循環語句,整個實現代碼顯得更加精練和高效。性能



更多Java技術文章參見《Java開發筆記(序)章節目錄指針

相關文章
相關標籤/搜索