Documentation

The Java™ Tutorials
Hide TOC
Data Streams数据流
Trail: Essential Java Classes
Lesson: Basic I/O
Section: I/O Streams

Data Streams数据流

Data streams support binary I/O of primitive data type values (boolean, char, byte, short, int, long, float, and double) as well as String values. 数据流支持基本数据类型值(booleancharbyteshortintlongfloatdouble)以及字符串值的二进制I/O。All data streams implement either the DataInput interface or the DataOutput interface. 所有数据流实现DataInput接口或DataOutput接口。This section focuses on the most widely-used implementations of these interfaces, DataInputStream and DataOutputStream.本节重点介绍这些接口最广泛使用的实现,DataInputStreamDataOutputStream

The DataStreams example demonstrates data streams by writing out a set of data records, and then reading them in again. DataStreams示例通过写出一组数据记录,然后再次读取来演示数据流。Each record consists of three values related to an item on an invoice, as shown in the following table:每个记录由与发票上的项目相关的三个值组成,如下表所示:

Order in record记录在案 Data type数据类型 Data description数据描述 Output Method输出方法 Input Method输入方法 Sample Value样本值
1 double Item price项目价格 DataOutputStream.writeDouble DataInputStream.readDouble 19.99
2 int Unit count单位计数 DataOutputStream.writeInt DataInputStream.readInt 12
3 String Item description项目说明 DataOutputStream.writeUTF DataInputStream.readUTF "Java T-Shirt"

Let's examine crucial code in DataStreams. 让我们研究一下DataStreams中的关键代码。First, the program defines some constants containing the name of the data file and the data that will be written to it:首先,程序定义一些常量,其中包含数据文件的名称和将写入其中的数据:

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"
};

Then DataStreams opens an output stream. 然后DataStreams打开一个输出流。Since a DataOutputStream can only be created as a wrapper for an existing byte stream object, DataStreams provides a buffered file output byte stream.由于DataOutputStream只能作为现有字节流对象的包装器创建,因此DataStreams提供缓冲文件输出字节流。

out = new DataOutputStream(new BufferedOutputStream(
              new FileOutputStream(dataFile)));

DataStreams writes out the records and closes the output stream.DataStreams写出记录并关闭输出流。

for (int i = 0; i < prices.length; i ++) {
    out.writeDouble(prices[i]);
    out.writeInt(units[i]);
    out.writeUTF(descs[i]);
}

The writeUTF method writes out String values in a modified form of UTF-8. writeUTF方法以UTF-8的修改形式写出String值。This is a variable-width character encoding that only needs a single byte for common Western characters.这是一种可变宽度字符编码,普通西文字符只需要一个字节。

Now DataStreams reads the data back in again. 现在,DataStreams再次读取数据。First it must provide an input stream, and variables to hold the input data. 首先,它必须提供一个输入流和保存输入数据的变量。Like DataOutputStream, DataInputStream must be constructed as a wrapper for a byte stream.DataOutputStream一样,DataInputStream必须构造为字节流的包装器。

in = new DataInputStream(new
            BufferedInputStream(new FileInputStream(dataFile)));

double price;
int unit;
String desc;
double total = 0.0;

Now DataStreams can read each record in the stream, reporting on the data it encounters.现在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) {
}

Notice that DataStreams detects an end-of-file condition by catching EOFException, instead of testing for an invalid return value. 请注意,DataStreams通过捕获EOFException而不是测试无效的返回值来检测文件结束条件。All implementations of DataInput methods use EOFException instead of return values.DataInput方法的所有实现都使用EOFEException而不是返回值。

Also notice that each specialized write in DataStreams is exactly matched by the corresponding specialized read. 还要注意,DataStreams中的每个专门write都与相应的专门read完全匹配。It is up to the programmer to make sure that output types and input types are matched in this way: The input stream consists of simple binary data, with nothing to indicate the type of individual values, or where they begin in the stream.由程序员来确保输出类型和输入类型以这种方式匹配:输入流由简单的二进制数据组成,没有任何东西来指示单个值的类型或它们在流中的起始位置。

DataStreams uses one very bad programming technique: it uses floating point numbers to represent monetary values. DataStreams使用了一种非常糟糕的编程技术:它使用浮点数来表示货币值。In general, floating point is bad for precise values. 一般来说,浮点不利于精确值。It's particularly bad for decimal fractions, because common values (such as 0.1) do not have a binary representation.这对于小数来说尤其糟糕,因为普通值(如0.1)没有二进制表示。

The correct type to use for currency values is java.math.BigDecimal. 用于货币值的正确类型是java.math.BigDecimalUnfortunately, BigDecimal is an object type, so it won't work with data streams. 不幸的是,BigDecimal是一种对象类型,因此不能用于数据流。However, BigDecimal will work with object streams, which are covered in the next section.但是,BigDecimal将处理对象流,这将在下一节中介绍。


Previous page: I/O from the Command Line
Next page: Object Streams