PrintStream 可以对数据进行格式化,以便人们的阅读。但是为了使输出可供另一个流恢
复的数据,我们必需用 DataOutputStream 写入数据,并用 DataInputStream 恢复数
据。当然,这些流可以是任何形式,但在这里我们采用的是一个文件,并且对于读和写都进
行了缓冲处理。注意 DataOutputStream 和 DataInputStream是面向字节的,因此要
使用 InputStream 和 OutputStreams。
如果我们使用DataOutputStream写入数据,Java保证我们可以使用DataInputStream
准确地读取数据——无论读和写数据的平台怎么不同。这一点具有不可思议的价值,因为我
们都知道人们曾经花费了大量时间去处理平台相关的数据问题。只要两个平台上都有Java,
这种问题就不会再发生3。
当我们使用DataOutputStream时,写字符串并且让 DataInputStream 能够恢复它的
唯一可靠的做法就是使用 UTF-8 编码,在例子第五部分中是用 writeUTF( ) 和 readUTF( )
来实现的。UTF-8 是 Unicode 的变体,后者把所有字符都存储成两个字节的形式。如果我
们使用的只是ASCII 或者几乎都是 ASCII 字符(只占 7 位),这么做就显得极其浪费空间
和带宽,所以UTF-8 将 ASCII 字符编码成单一字节的形式,而非 ASCII 字符则编码成两
到三个字节的形式。另外,字符串的长度存储在前两个字节中。但是,writeUTF( ) 和
readUTF( )使用的是适合于 Java 的 UTF-8 变体(在 JDK 文档中有这些方法的详尽描述),
因此如果我们用一个非 Java 程序读取用 writeUTF( )所写的字符串时,必须编写一些特殊
代码才能正确读取字符串。
有了 writeUTF( ) andreadUTF( ),我们就可以用DataOutputStream把字符串和其他
数据类型相混合,我们知道字符串完全可以作为 Unicode 来存储,并且可以很容易地使用
DataInputStream 来恢复它。
writeDouble()将 double 类型的数字存储到流中,并用相应的 readDouble()恢复它(对
于其他的数据类型,也有类似方法用于读写)。但是为了保证所有的读方法都能够正常工作,
我们必须知道流中数据项所在的确切位置,因为极有可能将保存的 double 数据作为一个简
单的字节序列、char 或其他格式读入。因此,我们必须要么为文件中的数据采用固定的格
式,要么将额外的信息保存到文件中,以便能够对其进行解析从而确定数据的存放位置。注
意:对象序列化(本章稍后会介绍)可能是更容易的存储和读取复杂数据结构的方式。