資料流
資料流支援原始資料型別值(boolean
、char
、byte
、short
、int
、long
、float
和double
)以及String
值的二進位制I/O,所有資料流都實現DataInput介面或DataOutput介面,本節重點介紹這些介面最廣泛使用的實現,DataInputStream和DataOutputStream。
DataStreams示例通過寫出一組資料記錄,然後再次讀取它們來演示資料流,每條記錄包含三個與發票上的條目相關的值,如下表所示:
訂單記錄 | 資料型別 | 資料描述 | 輸出方法 | 輸入方法 | 樣例值 |
---|---|---|---|---|---|
1 | double |
條目價格 | DataOutputStream.writeDouble |
DataInputStream.readDouble |
19.99 |
2 | int |
單位數 | DataOutputStream.writeInt |
DataInputStream.readInt |
12 |
3 | String |
條目描述 | DataOutputStream.writeUTF |
DataInputStream.readUTF |
“Java T-Shirt” |
我們來看看DataStreams
中的關鍵程式碼,首先,程式定義了一些常量,包含資料檔案的名稱和將寫入的資料:
static final String dataFile = "invoicedata";
static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };
static final int[] units = { 12, 8, 13, 29, 50 };
static final String[] descs = {
"Java T-shirt",
"Java Mug",
"Duke Juggling Dolls",
"Java Pin",
"Java Key Chain"
};
然後DataStreams
開啟輸出流,由於DataOutputStream
只能作為現有位元組流物件的包裝器建立,因此DataStreams
提供緩衝檔案輸出位元組流。
out = new DataOutputStream(new BufferedOutputStream(
new FileOutputStream(dataFile)));
DataStreams
寫出記錄並關閉輸出流。
for (int i = 0; i < prices.length; i ++) {
out.writeDouble(prices[i]);
out.writeInt(units[i]);
out.writeUTF(descs[i]);
}
writeUTF
方法以UTF-8
的修改形式寫出String
值,這是一種可變寬度的字元編碼,普通的西方字元只需要一個位元組。
現在DataStreams
再次讀回資料,首先,它必須提供輸入流和變數來儲存輸入資料,與DataOutputStream
一樣,DataInputStream
必須構造為位元組流的包裝器。
in = new DataInputStream(new
BufferedInputStream(new FileInputStream(dataFile)));
double price;
int unit;
String desc;
double total = 0.0;
現在,DataStreams
可以讀取流中的每條記錄,報告它遇到的資料。
try {
while (true) {
price = in.readDouble();
unit = in.readInt();
desc = in.readUTF();
System.out.format("You ordered %d" + " units of %s at $%.2f%n",
unit, desc, price);
total += unit * price;
}
} catch (EOFException e) {
}
請注意,DataStreams
通過捕獲EOFException來檢測檔案結束條件,而不是測試無效的返回值,DataInput
方法的所有實現都使用EOFException
而不是返回值。
另請注意,DataStream
中的每個專用write
都與相應的專用read
完全匹配,程式設計師應該確保以這種方式匹配輸出型別和輸入型別:輸入流由簡單的二進位制資料組成,沒有指示單個值的型別或它們在流中開始的位置。
DataStreams
使用一種非常糟糕的程式設計技術:它使用浮點數來表示貨幣值,通常,浮點對於精確值是不利的,對於小數部分尤其不好,因為常見值(例如0.1
)沒有二進位制表示。
用於貨幣值的正確型別是java.math.BigDecimal,不幸的是,BigDecimal
是一種物件型別,因此它不適用於資料流,但是,BigDecimal
將使用物件流,這將在下一節中介紹。