最后研究的读取器/编写器组是BinaryReader和BinaryWriter,它们都从System.Object直接派生。这些类型可以让我们从基层流中以简洁的二进制格式读取或写入离散数据类型。BinaryWriter类型定义了一个多次重载的Write()方法,用于把数据类型写入基层的流。除了Write()方法,BinaryWriter还提供了另外一些成员让我们能获取或设置从Stream派生的类型,并且提供了随机数据访问的支持(如表16-9所示)。
表16-9 BinaryWriter核心成员
成 员
作 用
BaseStream
这个只读属性提供了BinaryWriter对象使用的基层流的访问
Close()
这个方法关闭二进制流
Flush()
这个方法刷新二进制流
Seek()
这个方法设置当前流的位置
Write()
这个方法将值写入当前流
BinaryReader类补充了BinaryWriter的功能,表16-10列出了其中的一些成员。
表16-10 BinaryReader核心成员
成 员
作 用
BaseStream
这个只读属性提供了BinaryReader对象使用的基层流的访问
Close()
这个方法关闭二进制阅读器
PeekChar()
这个方法返回下一个可用的字符,并且不改变指向当前字节或字符的指针位置
Read()
读取给定的字节或字符,并把它们存入数组
ReadXXX()
BinaryReader类定义了许多ReadXXX()方法来从流中获取下一个类型(ReadBoolean()、ReadByte()、ReadInt32()等)
下面的示例新建了一个*.dat文件并且写入了一些数据类型:
static void Main(string[] args)
{
// 为文件打开一个二进制编写器。
FileInfo f = new FileInfo("BinFile.dat");
BinaryWriter bw = new BinaryWriter(f.OpenWrite());
// 输出类型的BaseStream(在这里是System.IO.FileStream)。
Console.WriteLine("Base stream is: {0}", bw.BaseStream);
// 在文件中存储一些数据。
double aDouble = 1234.67;
int anInt = 34567;
char[] aCharArray = { 'A', 'B', 'C' };
// 写数据。
bw.Write(aDouble);
bw.Write(anInt);
bw.Write(aCharArray);
bw.Close();
}
注意,从FileInfo.OpenWrite()返回的FileStream对象被传到BinaryWriter类型的构造函数中。使用这项技术就能很方便地在写入数据前引入一个流。需要理解的是,BinaryWriter构造函数能接受任何派生自Stream类型的参数(比如FileStream、MemoryStream或BufferedStream)。因此,如果希望向内存写二进制信息的话,只需提供一个MemoryStream对象即可。
BinaryReader类型提供了很多选项来从BinFile.dat文件读取数据。在这里,我们会使用PeekChar()来检测流中是否仍有可提供的数据,如果有的话,使用ReadByte()来取值。注意,我们用十六进制来格式化这些字节,并且在它们中间插入7个空格:
static void Main(string[] args)
{
// 为文件打开一个二进制编写器。
FileInfo f = new FileInfo("BinFile.dat");
...
// 以原始字节形式读取数据。
BinaryReader br = new BinaryReader(f.OpenRead());
int temp = 0;
while (br.PeekChar() != -1)
{
Console.Write("{0,7:x} ", br.ReadByte());
if (++temp == 4)
{
// 每4个字节一行。
Console.WriteLine();
temp = 0;
}
}
Console.WriteLine();
}