这些Java教程是针对JDK 8编写的。本页面中描述的示例和实践不利用后续版本中引入的改进,并可能使用不再可用的技术。
请参阅Java语言更改,了解Java SE 9及后续版本中更新的语言功能的摘要。
请参阅JDK发行说明,了解所有JDK版本的新功能、增强功能以及已删除或弃用选项的信息。
数据流支持对原始数据类型值(boolean、char、byte、short、int、long、float和double)以及字符串值进行二进制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恤" |
让我们来看看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恤",
"Java杯子",
"Duke戏法娃娃",
"Java别针",
"Java钥匙链"
};
DataStreamsDataOutputStreamDataStreams
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("您订购了%d件%s,价格为$%.2f%n",
unit, desc, price);
total += unit * price;
}
} catch (EOFException e) {
}
注意,DataStreams通过捕获EOFException来检测文件结束条件,而不是测试无效的返回值。所有的DataInput方法的实现都使用EOFException,而不是返回值。
还要注意,DataStreams中的每个专用write都与相应的专用read完全匹配。程序员需要确保以这种方式匹配输出类型和输入类型:输入流由简单的二进制数据组成,没有任何指示单个值类型或它们在流中开始位置的内容。
DataStreams使用了一种非常糟糕的编程技术:它使用浮点数来表示货币值。一般来说,浮点数对于精确值是不好的。对于小数部分来说尤其糟糕,因为常见的值(如0.1)没有二进制表示。
用于货币值的正确类型是java.math.BigDecimal。不幸的是,BigDecimal是一个对象类型,所以它不能与数据流一起使用。然而,BigDecimal可以与对象流一起使用,对象流将在下一节中介绍。