这些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钥匙链" };
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("您订购了%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
可以与对象流一起使用,对象流将在下一节中介绍。