流是 Java 中最基礎也最重要的概念之一。檔案讀寫、網路通訊、進程通訊,幾乎所有需要輸入輸出的地方都會用到流。流的本質是處理位元組序列:輸出流負責「取出」位元組,輸入流負責「送入」位元組。由於程式往往無法一次性處理所有資料,流提供了「讀一點、處理一點」的機制,恰如下載大型檔案時邊下載邊存檔。
所有流在 Java 中都是物件。InputStream(輸入流/讀取)與 OutputStream(輸出流/寫入)是兩大基礎抽象類。不同資料源獲取流的方式不同:檔案用 FileInputStream/FileOutputStream,網路用 Socket 獲取流。
public class ReadFileDemo {
public static void main(String[] args) {
String path = "c:/boot.ini";
File file = new File(path);
InputStream is = null;
try {
is = new FileInputStream(file);
byte[] content = new byte[0];
byte[] buffer = new byte[10240];
int eachTime = is.read(buffer);
while (eachTime != -1) {
content = concatByteArrays(content, buffer, eachTime);
eachTime = is.read(buffer);
}
System.out.println(new String(content));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) try { is.close(); } catch (IOException ignored) {}
}
}
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;
}
}
public class SaveFileDemo {
public static void main(String[] args) throws IOException {
File file = new File("c:/now.txt");
if (!file.exists() && !file.createNewFile()) return;
try (OutputStream os = new FileOutputStream(file)) {
os.write(new Date().toString().getBytes());
System.out.println("檔案寫入完成。");
}
}
}
Reader 與 Writer 是對位元組流的包裝,直接處理字符而非位元組,適合純文字內容:
// 使用 FileReader 讀取文字檔
Reader reader = new FileReader("c:/boot.ini");
char[] buffer = new char[10240];
int count;
String content = "";
while ((count = reader.read(buffer)) != -1) {
content += new String(buffer, 0, count);
}
更常用的是 BufferedReader 按行讀取:
BufferedReader reader = new BufferedReader(new FileReader("c:/boot.ini"));
String line;
while ((line = reader.readLine()) != null) {
content += line + "\n";
}
序列化將物件轉為位元組序列,可持久化或網路傳輸。ObjectOutputStream/ObjectInputStream 專門處理序列化/反序列化,要求類別實作 Serializable 介面:
public class SerializationDemo {
public static void main(String[] args) throws Exception {
String path = "c:/persons.data";
writePersons(path);
readPersons(path);
}
private static void writePersons(String path) throws IOException {
Person[] persons = { new Person("張三", 23), new Person("李四", 24) };
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path))) {
for (Person p : persons) oos.writeObject(p);
}
}
private static void readPersons(String path) throws IOException, ClassNotFoundException {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path))) {
while (true) {
try {
Person p = (Person) ois.readObject();
System.out.println(p);
} catch (EOFException e) { break; }
}
}
}
static class Person implements Serializable {
private String name; private int age;
// 建構子、getter/setter、toString
}
}
InputStream/OutputStream 是所有流操作的基礎Reader/Writer 及其緩衝實現finally 區塊或使用 try-with-resources 關閉流