基礎 IO 只認 byte[]/char[],寫入 int、String、陣列需手動轉換、協議設計,極易出錯。DataInputStream / DataOutputStream 封裝了標準二進制格式,提供 readInt()/writeInt()、readUTF()/writeUTF() 等類型安全方法,實現「寫什麼讀什麼,順序一致即可」。
⚠️ 鐵律:
DataOutputStream寫入的格式,只能 用DataInputStream按完全相同的順序、類型讀取。任何順序/類型不匹配都會導致資料錯位或 EOFException。
public class MyData {
boolean flag;
int number;
String text;
short[] scores;
public MyData() {}
public MyData(boolean flag, int number, String text, short[] scores) {
this.flag = flag; this.number = number; this.text = text; this.scores = scores;
}
}
import java.io.*;
public class WriteFileUseDataStream {
public static void main(String[] args) {
short[] scores = {1, 3, 134, 12};
MyData data = new MyData(true, 100, "Java語言", scores);
writeFile(data);
}
public static void writeFile(MyData data) {
// try-with-resources 自動關閉
try (FileOutputStream fos = new FileOutputStream("test.my");
DataOutputStream dos = new DataOutputStream(fos)) {
// 協議順序:flag → number → text → array_length → array_elements
dos.writeBoolean(data.flag);
dos.writeInt(data.number);
dos.writeUTF(data.text); // UTF-8 編碼 + 長度前綴
// 陣列寫入協議:先長度,再逐元素
dos.writeInt(data.scores.length);
for (short s : data.scores) {
dos.writeShort(s);
}
System.out.println("寫入完成,檔案格式已固化");
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.*;
public class ReadFileUseDataStream {
public static void main(String[] args) {
MyData data = readFile();
System.out.println("flag: " + data.flag);
System.out.println("number: " + data.number);
System.out.println("text: " + data.text);
for (short s : data.scores) System.out.print(s + " ");
}
public static MyData readFile() {
MyData data = new MyData();
try (FileInputStream fis = new FileInputStream("test.my");
DataInputStream dis = new DataInputStream(fis)) {
// 嚴格按寫入順序讀取
data.flag = dis.readBoolean();
data.number = dis.readInt();
data.text = dis.readUTF();
int len = dis.readInt(); // 讀取陣列長度
data.scores = new short[len];
for (int i = 0; i < len; i++) {
data.scores[i] = dis.readShort();
}
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
}
| 方法 | 二進制格式 | 說明 |
|---|---|---|
| writeBoolean | 1 byte (0/1) | |
| writeByte/Short/Int/Long | 1/2/4/8 bytes | 大端序 |
| writeFloat/Double | 4/8 bytes | IEEE 754 |
| writeUTF | 2 bytes 長度 + UTF-8 bytes | 長度限 65535,長字串用 writeString |
| writeChars | 每 char 2 bytes | 不寫長度,需預知長度 |
Data 流不綁定檔案,可搭配 ByteArrayOutputStream/InputStream 實現物件↔byte[] 雙向轉換:
// 序列化到 byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (DataOutputStream dos = new DataOutputStream(baos)) {
dos.writeInt(123);
dos.writeUTF("Hello");
}
byte[] bytes = baos.toByteArray(); // 可網路傳輸、存 Redis 等
// 從 byte[] 反序列化
try (DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes))) {
int n = dis.readInt(); // 123
String s = dis.readUTF(); // Hello
}
writeUTF 拋出 UTFDataFormatException,改用 writeBytes+長度或 ObjectOutputStream。DataInputStream/OutputStream 以標準二進制協議屏蔽了手動 byte[] 操作的複雜性,是 Java 內部儲存、進程間通訊、簡易序列化的利器。核心心法:**協議先行,順序為王,成對使用,自動關閉**。