8 _6 v. o' |, i5 `: q8 ~问题五,资源释放问题;/ ^: W' S0 r* a! x
8 A* f8 m w3 g3 k5 n6 K' _- T+ n' y3 @最后一个问题,说说如何使用Stream来更新大文件部分数据。 : P2 g% p0 Z P, ~. _) u4 h/ G, H! d* O
对于问题一,基本操作的问题,主要是读写问题,主要是出现在文件数据比较大,需要循环写或者读的时候。此时正确读的形式如下。 7 t5 ^2 @, z* o$ S* Y u4 D+ p& K
// Open a file to read- k7 V( [0 I% j, `: Z
6 G0 n+ x% B( h3 C& B' {) L using( FileStream fs = new FileStream( yourFile, # n: J0 W+ v6 o5 d$ I . w& H! P- \9 e7 d' b! A6 a8 | FileMode.Open, FileAccess.Read, ' ]8 k6 ^/ i2 O' u7 w! O9 U- o# w; { a/ D/ @
FileShare.None ) )/ Z& T( Z2 [ f _7 z k
8 s# N6 t0 S9 ?+ E! y {$ c: ^5 X5 y4 }! z2 w
% E& K5 m% h1 d int nRealRead = 0; 8 }' j1 m9 g) e5 |3 V& E. p, y5 h) n, G
byte[] bBuffer = new byte[1024];. G6 g$ x0 w$ a5 c
7 t9 n3 h! I8 q. m9 W$ r4 \
do 9 h7 s+ e" D+ S6 l+ `' _9 k" [# l. ~; ?9 D$ l! {: M
{6 C4 X3 s( W- W8 c( S. C8 m* \& ]
' ]: h) E }" _ // Read data* Z/ S0 s! A( j# Z" j0 D+ {
% q. o5 N# v& A& Q w
nRealRead = fs.Read( bBuffer, 0, 1024 );" R) M+ f! W, V: ]" d8 E
) X( i7 i N" j0 j5 ?
// Output data+ ?1 ~# Z9 M/ H: R3 R) I; t/ }
* w- H: r s" G; H' X
Debug.WriteLine( Encoding.Default.GetString( bBuffer, 0, nRealRead ) ); * I% Y* W. ~) `2 F / Z( p8 F3 g) E. \9 W9 }- h }while( nRealRead == 1024 );7 F" ]9 E. C. R& c1 f( `9 V9 R
( h8 a0 Q. i# o" B8 b* N7 \
} 3 M8 Y- {: D) A$ k% h( d. Z* J" Y) e3 p ~ ?
可是大多数人第一次完成这样操作的时候,都会在“nRealRead = fs.Read( bBuffer, 0, 1024 );”这一句犯错误。认为第二个参数的偏移量对于Stream而设的,所以认为应该用累加的值,也就是目前总共读了多少的字节数。这里需要理解一下Stream的操作,当进行读或者写操作的时候,Stream的游标会根据所读或者所写得字节而自动向前跟进;其次Stream.Read或者Stream.Write这两个方法中第二个参数是针对第一个Buffer参数而言的,而不是对于Stream的,因此不要在这个地方犯错误。$ k3 ]1 B, ~) O
7 p( Z/ N! R: r! E1 y% j; c, W: P1 `基本问题还牵扯的就是文件打开的方式。有人经常问,如何同时用两个Stream打开同一个文件。其实默认的Stream打开方式是独享的,因此当不指明文件为访问共享的时候,后打开文件操作就会出现异常,因此需要向我上面所写的那样。还有,如果需要指定当前Stream的起始位置,可以通过Seek方法或者设置Position属性来完成。 $ g2 R( h8 x( Z' J C$ Z9 s' \" h$ k. u, q9 j# ?
对于问题二,编码问题。有人使用Stream的子类,例如StreamReader之类来打开一个文本文件,发现读出来的数据是乱码,造成这个原因大多数由于文件中含有中文字符,同时打开文件的时候没有指明编码方式。由于英文和中文的编码方式不同,因此在不指明编码的时候有时会造成读取中文错误。此时只要使用StreamReader类型中含有Encoding参数的构造函数即可,例如:/ ~% u( e0 ?: ?
) n0 j0 ] I, I4 L2 m }( C6 l
using( StreamReader sr = new StreamReader( yourFile, Encoding.Default ) )5 \( y8 i1 P1 ?
5 N0 \ g8 k+ m2 Z4 ~
这里只是采用系统默认的编码方式,但有可能不太适合你文件的编码方式,因此需要在实际应用去调试和变换这个参数。* Q4 O& D$ E" X
& ~0 r4 x6 c; K4 e2 B! j7 }: |6 }问题三是,Stream尾部处理问题。此类问题所展现的现象如,复制文件的时候文件会增大。因此在使用Stream.Read和Stream.Write的时候,要通过方法的返回值,来标明真正读和写的字节数,就像前面所写的那样。 4 O ?& i4 H# }/ M # N2 Q7 P4 v( i // Read data& r M7 T6 j; n! k' S
( w( x4 b* J3 Y% d nRealRead = fs.Read( bBuffer, 0, 1024 ); & M9 m8 K' s* H+ u: K1 F- s 3 O* r# v9 z# _6 } // Output data4 O6 `8 r% i( b& j: U9 E
3 B. i: z W' P" \2 i" H4 |
Debug.WriteLine( Encoding.Default.GetString( bBuffer, 0, nRealRead ) );8 \8 r: q3 O4 H7 p
# b4 ^. K$ s* u* l
此时在输出的时候用的不是“1024”,而是“nRealRead”做为字节有效标示。 6 z4 `4 u$ C z. { / n8 S: b. S! E0 G3 C对于问题四,Stream缓存的问题,这主要表现在写的时候。为了避免频繁操作IO而降低效率,大多数Stream采用异步写的方式,也就是Stream对象要配备有一定的缓存,来暂时保存写的数据。但缓存是有限的,当缓存已满后会造成后续写的数据不能写入,从而导致数据丢失。那么此时需要显示的调用Stream.Flush方法,来把缓存的数据写入到文件中并清空缓存。其实这并不是唯一方法,在一些Stream的子类中还提供了设置BufferSize的方法,或者提供了设置AutoFlush属性来实现自动写入等等,因此这里大家可以根据不同需要而选择不同方法来完成。' Y# q j$ ]* X3 U9 k. K$ m3 X