把握vb.net中的流(stream) (二)
灵活多样的io操作
有时候,在数据和字节数组之间转换是一件繁琐的事情。为了避免这些无聊的转换和简化代码,采用streamreader/streamwrite和binaryreader/binarywriter不愧为明智之举。streamreader/streamwrite分别由textreader/textwriter类派生,自动执行字节编码的转换。binaryreader/binarywriter由stream派生,主要以二进制的形式读写数据。
从二进制文件读数据的时候,首先创建一个binaryreader的实例,binaryreader的构建函数接受一个filestream对象,代表将要读的文件。我们前面已经看过,可以用file.openread 或者 file.openwrite 方法创建filestream对象。
如下所示:
dim br as new io.binaryreader(io.file.openread(path))
dim bw as new io.binarywriter(io.file.openwrite(path))
binarywriter类有write和writeline两种方法,都可以接受任何类型的数据作为参数写入文件(writeline在文件尾追加一行数据)。binaryreader类有很多读数据的方法,数据存储在文件上的时候,并没有任何关于自己类型的信息,所以读数据的时候,必须选择合适的重载read方法。
下面的例子假设bw是一个已经初始化过的binarywriter对象,表示如何写一个字符串、整数、双精度数字到文件:
bw.writeline("a string")
bw.writeline(12345)
bw.writeline(123.456789999999)
读回数据的时候,必须选择binaryreader合适的read方法:
dim s as string = br.readstring()
dim i as int32 = br.readint32()
dim dbl as double = br.readdouble()
对于文本文件,采用streamreader/streamwriter对象。方法跟上面差不多,写数据同样用write和writeline方法。read方法读一个字符,readline读一行数据(直到有回车/换行符为止),readtoend读所有的字符,到文件结束。
对象序列化
到目前为止,我们只是把简单类型的数据写到文件中并读回程序。而实际上,大多数的程序读写的数据可能并不是简单类型,而是复杂的结构,例如:数组,数组列表,哈希表等。于是,我们采取一种成为序列化的技术,首先把数组的值转化为字节序列,然后写入文件,这样整个数组就存储下来。相反,我们称之为反序列化。
序列化是.net的一个很大的话题,这列介绍一下基本的信息。
用binaryformatter的serialize 和 deserialize方法把一个对象保存到文件和读回程序。首先,imports system.runtime.serialization.formatters,免得写那么长的申明。formatters名空间包含了binaryformatter类,用于以二进制的数据序列化对象。
创建binaryformatter实例,接着调用serialize方法,serialize接受两个参数:一个是可写的filestream实例,用于保存数据的文件;另外一个是对象本身:
dim binformatter as new binary.binaryformatter()
dim r as new rectangle(10, 20, 100, 200)
binformatter.serialize(fs, r)
binaryformatter的deserialize方法只有一个参数,filestream实例。在当前位置,反序列化得到一个类型不明的对象,我们必须用ctype转换为原来的对象。下面的例子反序列化上面的文件得到原来的rectangle对象:
dim r as new rectangle()
r = ctype(binformatter.deserialize(fs), rectangle)
我们也可以以xmlformatter进行对象序列化。首先在ide的project菜单选择添加system.runtime.serialization.formatters.soap,然后就可以进行创建soapformatter对象了,方法跟binformatter一样,只不过数据的存储采用xml格式:
dim fs as new io.filestream("c:\rect.xml", io.filemode.create, io.fileaccess.write)
dim xmlformatter as new soapformatter()
dim r as new rectangle(8, 8, 299, 499)
xmlformatter.serialize(fs, r)
打开c:\rect.xml ,实际上里面存储了这些内容:
– <soap-env:envelope xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:xsd="http://www.w3.org/2001/xmlschema" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" soap-env:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/">
– <soap-env:body>
– <a1:rectangle id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/system.drawing/system.drawing%2c%20version%3d1.0.3300.0%2c%20culture%3dneutral%2c%20publickeytoken%3db03f5f7f11d50a3a">
<x>8</x>
<y>8</y>
<width>249</width>
<height>499</height>
</a1:rectangle>
</soap-env:body>
</soap-env:envelope>
