流和序列化(一)--流

来源:互联网 发布:淘宝电话诈骗后怎么办 编辑:程序博客网 时间:2024/05/02 14:44

        在c#中,流被实现为了Stream类及一系列的子类,同时还有一些装饰类和帮助类。流的最主要用途就是与应用程序外部的文件或数据员进行数据交互。比如,访问文件时,有文件流(FileStream);访问网络时,有网络流(NetStream);访问串口时,虽然没有流的子类型,但是SerialPort类型暴力了BaseStream属性;访问Web服务器时,HttpRequest和HttpResponse类型也包含InputStream和OutputStream属性。流与字节数组Byte[]不同,Byte[]是一个静态的数据容器,它本身保存了全部的数据;而流是一个动态的概念,按照字节的次序进行顺序访问,每次可以只访问单个字节或者连续的一段。

      通常在使用流时,我们会用使用到Byte[]数组用来保存临时数据。Byte[]数组的大小可以设置为与文件大小一样,然后一次性写入新文件,这样看上去简单直接,但是有两个问题:1.如果文件很大,那么将文件完全读取到应用程序的Byte[]数组中,内存消耗十分大!

2.如果文件位于远程服务器上,传输开始时无法知道文件大小,只有传完才知道。所以,通常将Byte[]设置为固定的大小,比如1024个字节,然后将读取的操作写在一个循环中,每次先读取1KB,将1KB处理后转存到别的地方,直到读完文件中的所有数据。此时,Bytep[]保存的是临时数据,下次循环式丢弃。Byte[]相当于一个临时缓存,因此通常会将它命名为buffer。

      

1.一次性复制

   Stream source=new FileStream(@"D:\head.txt",FileMode.Open,FileAccess.Read);   [1]

   byte[]  buffer=new byte[source.length];                                                                                  [2]

   int bytesRead =source.Read(buffer,0,(int)source.length);                                                   [3]


[1]中3个参数解析,第一个参数指定文件路径,第二个参数是一个枚举,指定操作系统打开文件的方式,第三个参数表明打开文件的意图。

[2]将文件通过流保存到应用程序中的Byte[]数组中。由于数组的长度是固定的,在声明时要确定。但是不是所有流都可以访问Length属性。比如文件位于远程服务器,通过NetworkStream来访问,这种情况,访问length属性会抛出异常。

[3] Read()方法接受三个参数,第一个参数表示将要写入的字节数组,第二个参数是相对于文件头的偏移量,设定从文件哪个位置开始读取。当为0时,表示从文件头开始。第三个参数表示读取的字节数。

注:Read方法返回读取到的字符数,当返回0时,表示读到了文件末尾,也就是流终点。至此就完成了将图片转换为Byte[]数组的所有工作。


2.循环分批复制


以上代码需要注意三处:

1.定义了一个BufferSize变量,声明数组和读取流时,使用BufferSzie变量,而不是直接使用10240.这是为了避免出现前后不一致的情况。

2.Read()和Write()方法的第二个参数一直保持为0。这个参数是读取或写入buffer时相对于数组第一个元素的偏移量。因为本例要写入和读出buffer全部字节,所以从0开始。

3.当打开文件或者创建文件时,流指针默认位于头文件,当调用Read()或者Write()时,流指针会自动向后移动相应的字节数。




Read方法:从流中读取数据到字符块中

write方法:从字符块中读数据到流。

0 0
原创粉丝点击