Data Streams

数据流支持原始数据类型值(booleancharbyteshortintlongfloatdouble)的二进制 I/O 以及字符串 值。所有数据流都实现DataInputinterface或DataOutputinterface。本节重点介绍DataInputStreamDataOutputStream这些interface的最广泛使用的实现。

DataStreams示例通过写出一组数据记录,然后再次读入它们来演示数据流。每个记录都包含与发票上的项目相关的三个值,如下表所示:

Logging 的订单Data typeData descriptionOutput MethodInput MethodSample Value
1doubleItem priceDataOutputStream.writeDoubleDataInputStream.readDouble19.99
2intUnit countDataOutputStream.writeIntDataInputStream.readInt12
3StringItem descriptionDataOutputStream.writeUTFDataInputStream.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再次读回数据。首先,它必须提供 Importing 流和变量以保存 Importing 数据。像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通过catchEOFException来检测文件结束条件,而不是测试无效的返回值。 DataInput方法的所有实现都使用EOFException而不是返回值。

还要注意,DataStreams中的每个专门write与对应的专门read完全匹配。程序员应确保以这种方式匹配输出类型和 Importing 类型:Importing 流由简单的二进制数据组成,没有任何内容可以指示单个值的类型或它们在流中的起始位置。

DataStreams使用一种非常糟糕的编程技术:它使用浮点数来表示货币值。通常,浮点数对精确值不利。对于小数部分而言,这特别糟糕,因为公用值(例如0.1)没有二进制表示形式。

用于货币值的正确类型是java.math.BigDecimal。不幸的是,BigDecimal是一种对象类型,因此它不适用于数据流。但是,BigDecimal将与对象流一起使用,这将在下一节中介绍。