原作者為csdn上的 YidingHehttp://blog.csdn.net/YidingHe
本人打算寫幾篇文章,介紹一下流。本文是針對初學者的,加上本人水平有限,所以不敢說寫得很高深。如果你是初學者,而且對流這個東西很頭疼,你就應該看看這個。
本文發表在:http://blog.csdn.net/YidingHe,轉載請保留出處。
流是 Java 中最重要的基本概念之一。文件讀寫、網絡收發、進程通信,幾乎所有需要輸入輸出的地方,都要用到流。
流是做什么用的呢?就是做輸入輸出用的。為什么輸入輸出要用“流”這種方式呢?因為程序輸入輸出的基本單位是字節,輸入就是獲取一串字節,輸出就是發送一串字節。但是很多情況下,程序不可能接收所有的字節之后再進行處理,而是接收一點處理一點。比方你下載魔獸世界,不可能全部下載到內存里再保存到硬盤上,而是下載一點就保存一點。這時,流這種方式就非常適合。
在 Java 中,每個流都是一個對象。流分為兩種:輸入流(InputStream)和輸出流(OutputStream)。對于輸入流,你只要從流當中不停地把字節取出來就是了;而對于輸出流,你只要把準備好的字節串傳給它就行。
______________Java 程序____________
| |
外部系統 --|--(輸入流)--> 處理邏輯 --(輸出流)---|--> 外部系統
|_________________________________|
流對象是怎么獲得的呢?不同的外部系統,獲取流的方式也不同。例如,文件讀寫就要創建 FileInputStream/FileOutputStream 對象,而網絡通信是通過 Socket 對象來獲取輸入輸出流的。一般來說,如果一個類有 getInputStream() 或 getOutputStream() 這樣的方法,就表明它是通過流對象來進行輸入輸出的。
InputStream 是輸入流,下面是一個通過 InputStream 讀取文件的例子:
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.FileNotFoundException;
- import java.util.Arrays;
-
- /**
- * 通過流讀取文件
- */
- public class ReadFileDemo {
-
- // 程序入口
- public static void main(String[] args) {
- String path = "c:/boot.ini";
- File file = new File(path);
-
- // 創建輸入流
- InputStream is;
- try {
- is = new FileInputStream(file);
- } catch (FileNotFoundException e) {
- System.err.println("文件 " + path + " 不存在。");
- return;
- }
-
- // 開始讀取
- byte[] content = new byte[0]; // 保存讀取出來的文件內容
- byte[] buffer = new byte[10240]; // 定義緩存
-
- try {
- int eachTime = is.read(buffer); // 第一次讀取。如果返回值為 -1 就表示沒有內容可讀了。
- while (eachTime != -1) {
- // 讀取出來的內容放在 buffer 中,現在將其合并到 content。
- content = concatByteArrays(content, buffer, eachTime);
- eachTime = is.read(buffer); // 繼續讀取
- }
- } catch (IOException e) {
- System.err.println("讀取文件內容失敗。");
- e.printStackTrace();
- } finally {
- try {
- is.close();
- } catch (IOException e) {
- // 這里的異常可以忽略不處理
- }
- }
-
- // 輸出文件內容
- String contentStr = new String(content);
- System.out.println(contentStr);
- }
-
- /**
- * 合并兩個字節串
- *
- * @param bytes1 字節串1
- * @param bytes2 字節串2
- * @param sizeOfBytes2 需要從 bytes2 中取出的長度
- *
- * @return bytes1 和 bytes2 中的前 sizeOfBytes2 個字節合并后的結果
- */
- private static byte[] concatByteArrays(byte[] bytes1, byte[] bytes2, int sizeOfBytes2) {
- byte[] result = Arrays.copyOf(bytes1, (bytes1.length + sizeOfBytes2));
- System.arraycopy(bytes2, 0, result, bytes1.length, sizeOfBytes2);
- return result;
- }
- }
雖然寫得很啰嗦,但這確實是 InputStream 的基本用法。注意,這只是一個例子,說明如何從輸入流中讀取字節串。實際上,Java 提供更簡單的方式來讀取文本文件。以后將會介紹。
相比從流中讀取,使用 OutputStream 輸出則是非常簡單的事情。下面是一個例子:
- import java.io.OutputStream;
- import java.io.FileOutputStream;
- import java.io.File;
- import java.io.IOException;
- import java.util.Date;
-
- /**
- * 將當前日期保存到文件
- */
- public class SaveFileDemo {
-
- public static void main(String[] args) throws IOException {
- String path = "c:/now.txt";
-
- File file = new File(path);
- if (!file.exists() && !file.createNewFile()) {
- System.err.println("無法創建文件。");
- return;
- }
-
- OutputStream os = new FileOutputStream(file); // 創建輸出流(前提是文件存在)
- os.write(new Date().toString().getBytes()); // 將當前時間寫入文件
- os.close(); // 必須關閉流,內容才會寫入文件。
- System.out.println("文件寫入完成。");
- }
- }
Java 還提供其它的流操作方式,但它們都是對 InputStream 和 OutputStream 進行擴展或包裝。所以這兩個類是基礎,必須要理解它們的使用。