文档

Java™教程
隐藏目录
数据流
教程:基本Java类
课程:基本I/O
部分:I/O流

数据流

数据流支持对原始数据类型值(booleancharbyteshortintlongfloatdouble)以及字符串值进行二进制I/O操作。所有数据流都实现了DataInput接口或DataOutput接口。本节重点介绍这些接口的最常用实现,即DataInputStreamDataOutputStream

示例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可以与对象流一起使用,对象流将在下一节中介绍。


上一页: 从命令行进行输入输出
下一页: 对象流