1、基本的輸入流和輸出流
流是 Java 中最重要的基本概念之一。文件讀寫、網絡收發、進程通信,幾乎所有需要輸入輸出的地方,都要用到流。
流是做什么用的呢?就是做輸入輸出用的。為什么輸入輸出要用“流”這種方式呢?因為程序輸入輸出的基本單位是字節,輸入就是獲取一串字節,輸出就是發送一串字節。但是很多情況下,程序不可能接收所有的字節之后再進行處理,而是接收一點處理一點。比方你下載魔獸世界,不可能全部下載到內存里再保存到硬盤上,而是下載一點就保存一點。這時,流這種方式就非常適合。
在 Java 中,每個流都是一個對象。流分為兩種:輸入流(InputStream)和輸出流(OutputStream)。對于輸入流,你只要從流當中不停地把字節取出來就是了;而對于輸出流,你只要把準備好的字節串傳給它就行。
流對象是怎么獲得的呢?不同的外部系統,獲取流的方式也不同。例如,文件讀寫就要創建 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; } }