|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
文件流) z, `, n0 Q @3 u* \8 D% h
* d6 G. u, x" r+ b! X" B# x& J
一、流的概述
0 o) V9 r" |! Q9 Y3 u# Q2 o0 e- M 要完成文件的读写操作,就必须了解C#中另外一个重要的概念——流(Stream)
& `& N5 E2 A- C8 e C#中流的概念可以和生活中的流相对应。在生活中有水流和电流,首先要有一个源头,还需要有传输的管道,
! d( c! q2 A& h; q4 r5 B# [9 S, w水流有河道、水管作为传输管道,电流有电线,而这些流都会有一个目的,就是它的流向。C#的流也需要源头——文件、数据流入流出管道以及数据的访问。
; C4 O' a, G# v z0 H T1、输出流和输入流 .Net Framework中进行的所有输入、输出工作都需要用到流。
- i- M$ P& E, r4 l 1、输出流:当向某些外部目标写入数据时,就要用到输出流。" H3 ]1 O: _5 n* B3 \
2、输入流:用于将数据读到程序访问的内存或变量中。! G; \0 ~0 H- c; s+ X/ ^1 T t
在程序的控制台中的可以理解为:+ S9 T; l1 K/ W3 U
输出流:控制台程序中,将信息从程序中输出的处理:Console.WriteLine();
$ T2 R" a I- m. `输入流:通过用户键盘来输入到程序当中处理:Console.ReadLine();' }8 q/ _( f8 V5 L% E
2、文件读写,常用的三个类对于文件读写,常见的三个类:0 H# d) L9 v/ Z
1、FileStream(文件流):这个类主要用于在二进制文件中读写二进制数据——也可以使用它读写任何文件。1 j: v7 R- Z4 b3 O
2、StreamWriter(流写入器)和StreamReader(流读取器):这二个类是专门用来读写文本文件的。$ I. B" H/ E- z, u# _, g, y! G
二、FileStream对象### 1、FileStream对象的二种重载 FileStream对象表示在磁盘或网络路径上指向文件的流。这个类提供了在文件中读写字节的方法。. n3 H% [3 L, A5 i
有多种方法可以创建FileStream对象,FileStream类的构造函数有很多的重载版本,最简单的重载版本仅带有二个参数,即文件路径和FileModel枚举值。2 q& E" @: D9 i
1.1、第一种重载:
4 {8 @( g, B1 u, d2 h) _. T
; @6 b! {% O' R& n" L' @ e* G. w- S4 S9 R, P4 Q) P* H( e7 [1 W7 ]
) T( F) G& m$ i2 T3 e* C i- e- L; b- FileStream aFile = new FileStream( 文件路径 , FileMode.成员值);7 w% R. R1 K3 W8 F/ J1 x
5 | o4 t* ]5 J0 d1 W+ d& S
1 a h* O: |3 D3 g7 J3 S! i: a. g7 W9 H# w; W
4 _+ F$ F/ y6 d- JFileModel的枚举成员:
, D# y U" Y) Q![]() 7 A- N; Q" \. x- Z4 ]7 [' d
1.2、第二种重载:
- U3 x, k6 q) u; ]) {' A8 e/ p; S2 ?& W
6 D* ~+ {0 k5 I: i9 n% y7 Q% Q
) ^& {+ |) X; F. T* L. T" Y6 u) ]- FileStream aFile = new FileStream( 文件路径, FileMode.成员值, FileAccess.成员值);1 T9 W4 n3 u* G4 Y# r
+ o: O8 |; o2 J' Z
0 H4 A" N' p5 \; r& ^3 [. d9 T" L8 K
9 ~: m# A8 Z3 q7 ~! C8 P; EFileAccess的枚举成员:
# k ]8 d- i9 Q4 ~' k7 ?+ p4 Q8 `, V0 @6 Y1 B# O- C
在FileAccess构造函数不使用FileAccess枚举参数的版本中,使用默认值FileAccess.ReadWrite。
, ]4 b( s! E" j8 n File和FileInfo类中都提供了OpenRead()和OpenWrite()方法,使程序更易于创建FileStream对象。前者打 开了只读访问的文件,后者只允许写入文件。* @$ l% Q+ ], l: C
这些都提供了快捷方式,因此不一定要以FileStream构造函数的参数形式提供前面所有的信息。例如,下面的代码行打开了用于只读访问的Data.txt文件。
2 ~/ r& r7 f/ N; K9 l
- b+ O; L* b, ^% M R, r
7 t9 v. r- ~8 H/ m2 U9 Y' v# b; E) Z/ c" x
- e4 n1 y; s! X7 |& h. Q/ k- FileStream aFile=File.OpenRead(@“C:\Data.txt”);
7 }: l ]$ X" m3 q0 n& ~$ H 0 L0 D0 W. A+ j' ~% h( E
& R" k; b# S3 ~) u6 e: D$ t- p: [6 N% @1 I0 N2 B9 E, g
2 c0 w. j& s* n" }' U+ x" {7 s* x/ | q# g
或者
3 G" D/ J5 P- P7 o# P6 K) q2 ~- i& w0 }4 m) z0 I9 M
5 Z- I. @7 p' U% _
0 ]" y6 V! a/ I# l: Z/ h8 v6 o: d% h, }
- FileInfo aFileInfo=new FileInfo(@“C:\Data.txt”);/ x* b' ^( g# p! }4 j2 a
; k. p- ]) B' e! h
/ b: y# g: j5 Z" {9 _7 h4 w4 e' p" u2 u" H
. P s9 T: ] N7 C
; L. W' [" ]4 o# m( j: U
, q3 W( y: u6 m8 \3 o# t' O F f2 D) x- t( ~' d
. U: }) p6 v: G; M& F1 T
% R: \- J& F V" g5 X% R2 {! ^' d6 ]4 K7 E
- FileStream aFile=afileInfo.OpenRead();
3 Q2 E- V& ~4 l- H7 N, B9 s : h# ~4 a$ N" b( L# ?! g j2 F
9 j" C/ u4 x% `( s1 w; h; H+ K, \4 k( O) D2 G+ f: O
9 Z& F1 Q9 m: f5 x; t& l. `
2、使用FileStream读取数据和写入数据 使用FileStream类读取数据并不容易,这是因为FileStream类只能处理原始字节(Raw Byte)。
. |$ {( c( ]+ Q |; G3 ~- X FileStream对象的Read()方法是从FileStream对象所指向的文件访问数据的主要手段。这个方法从文件中读取数据,再把数据写入一个字节数组。4 D2 H0 n5 R7 b6 k/ T
" E$ z& c% c6 I: t9 W+ a
该方法有三个参数:第一个参数是传入的字节数组,用以接收FileStream对象中的数据。第二个参数是字节数组中开始写入数据的位置。通常是0,表示从数组开端开始放置读入的字节。最后一个参数指定从文件中读出多少字节。. m- u% n* N1 `: c4 J/ E3 k$ Q
& G+ A! w# q [/ S. Q# ?7 G
2.1、读取数据:8 p5 ^3 j0 e3 p
在编写程序代码前,需导入Sysytem.IO命名空间。此应用程序打开了磁盘上某个文件,用于读取其中的部分数据。首先,通过实例化一个FileStream的对象,将流指向这个文件。0 v5 j" v' ~1 }( C+ W X& T
这可以通过:! h; f4 n+ b' i4 c* f: X5 X. o
; \7 Z, t, P- `9 q0 {
8 v& S; P2 `7 t' ~. ]3 v
& v9 N0 i) T+ x* I! k. g/ p' I6 M) r4 \: K" G
- FileInfo aFileInfo =new FileInfo(@"C:\My Document\ReadMe1.txt");
- FileStream aFileInfo =aFileInfo.OpenRead();
+ C& r, T6 P! Z7 w# `# K) J+ u
) T; K& B- s. n: S, I& }" S' h6 t8 c7 X3 y! _" j4 t
S5 U/ U0 C9 {
; G4 B: v/ Z' N; a) o" [2 O
步骤:创建FileStream对象,并指向文件流——得到文件大小(字节单位)——创建一个相同大小的字节数组——将文件的字节内容读到数组中——将数组中字节转为字符——输出显示——关闭流
" j5 b2 r' d M; n$ q- K) }' f* a
, B+ k4 z( M# t9 e6 e4 r: P. A. o" c7 N. O$ A# G$ C
Z$ W' v, i( L1 @, p0 Y7 n5 e7 D$ {5 g2 ]& k
- /// <summary>
- /// 读取数据
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void button1_Click(object sender, EventArgs e)
- {
- //以只读方式创建FileStream对象
- FileStream afile = new FileStream(@"C:\My Document\ReadMe1.txt",FileMode.OpenOrCreate);
- //得到文件的长度/大小
- long length = afile.Length;
- //使用文件的长度创建一个字节数组。
- byte[] Buffers = new byte[length];
- //将流中的数据的字节内容读到字节数组中
- afile.Read(Buffers, 0, Buffers.Length);
- //将读到的数据进行转码,转为字符串
- string content = Encoding.Default.GetString(Buffers, 0, Buffers.Length);
- //将字符串在文件框中显示
- richTextBox1.AppendText(content);
- //关闭流对象,释放文件引用。
- afile.Close();
- }
3 O+ G7 U7 X" I5 ` ! m+ B5 f* ~6 L7 R, I1 w- ~
6 J# D0 r3 w( @% U, ^" I
0 [8 J( s( F0 A4 ~+ b/ ]+ h' ^1 r5 \: g& |/ {. ]
2.2、写入数据:* B$ |) D, U& g& l
步骤:创建FileStream对象,并指向文件流——声明一个数组是写入数据字节的2倍——使用Encoding类的GetBytes()方法将字符串中的一组字符编码到字节数组中,(1、编码的字符集的字符串,2、表明第一个编码的字符的索引,3、要编码的字符的数量,4、表明要包含所产生的字节序列的字节数组,5、开始写入所产生的字节序列索引位置)
7 u# z8 k P+ d u
3 K1 v8 @3 `: [5 X) G4 t( H; y& t: j
$ r* N' {% G: @2 o2 {; v. q) ]9 c
% H, f: F& u+ U
- /// <summary>
- /// 写入数据
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void button2_Click(object sender, EventArgs e)
- {
- //创建一个写文件的文件流对象
- FileStream aFile = new FileStream(@"C:\My Document\ReadMe1.txt",FileMode.OpenOrCreate, FileAccess.Write);
- //创建字节数组
- byte[] buffers;
- //获取传入闻见的字符串
- string content = richTextBox1.Text;
- //为字节数组分配字符串
- //可能会包含中文,可以将长度设为字符串长度的二倍
- buffers = new byte[content.Length * 2];
- //将字符串转成字节放入字节数组中
- Encoding.Default.GetBytes(content, 0, content.Length, buffers, 0);
- //将字节数组写入文件中
- aFile.Write(buffers, 0, buffers.Length);
- //关闭流对象,释放文件引用。
- aFile.Close();
- }1 U) {+ z+ a1 D" @
) X5 U0 n: H% n; |3 v0 X1 @' Y; w% H; h- F$ l" H
8 G' z# ^! l* x1 p8 M1 Z
* m! j0 ?) F! ?9 r$ P4 c d, I三、StreamWrite和StreamReader对象1、StreamWriter对象
% g1 o% I( w& z1 uStreamWriter对象只能用于写入文件(或另一个流),StreamWriter类的构造方法有很多版本。最常用的有以下三种。
$ r. O+ }2 H- i/ G& z. |+ h% l9 B/ E! S* X$ v" D4 c$ N
7 T9 `* B. u3 i3 H
& t9 N4 T l; W: o+ `* U# _. o4 W$ X) D7 h
- StreamWriter sw=new StreamWriter(@ “C:\test.txt”);
) D' L, g7 W- ]
e( r) C6 \* q) A4 _+ L v8 C/ f0 R- i& T1 p
* G8 A% p/ x) b4 c% t: R- i' p% h
3 b# H& \2 X6 i& \, o# |将使用UTF-8的编码方式创建StreamWriter对象,.NET把这种编码设置为默认的编码方式。+ b( p5 y0 f+ c8 _7 Q' s
$ R, A5 R5 {+ c* i( Y7 W' t8 G; ^9 A- @: l9 H0 a( D
5 T' n0 K1 L z! y. G9 D5 |; l4 ^7 j
8 J- t% t- {* v, O
- StreamWriter sw=new StreamWriter(@ “C:\test.txt”, true);
0 ^9 {+ `+ L' @2 H
, ?1 K8 O$ W6 z. j/ F! Y# @9 i+ t w; r1 s: r. i$ a) s# g
% \% R+ y; L2 L( j9 H: Q) L; n+ N/ D: {
% V$ o3 @1 N+ [# i
$ X- z5 R; B5 ^7 I' U
在这个构造函数中,第二个参数是bool类型,表示文件是否以追加的方式打开。
' a& o7 `6 M+ Q# ~) x1 D7 a
6 F. i- |: y5 e6 X- V: z# A6 `) v" h4 W Z8 c9 Z0 A
0 ^/ {. ^$ p1 E; V! V$ `
' C, I. \1 M0 k9 I& Y: O
- StreamWriter sw=new StreamWriter(@ “C:\test.txt”,true,Ecoding.ASCII);
( I1 d3 n7 z+ |. t& Z" B
/ S5 A" F' R( _1 [/ f. m3 q- ?2 {, R* w
. P1 S/ V0 j9 e6 f- D, M& j3 q
1 w# x" k& ]; ]8 e* _7 D8 u& N! I
( b' E+ r7 M5 t5 e- {在第三个函数中,第三个参数可以指明要使用的编码方式ASCII来创建StreamWriter对象。但不能仅以文件名和编码方式来创建对象。/ h4 {, T# b, f! r( F2 U# c* X* b: W
当然,也可以将StreamWriter关联到一个文件流上,以获得打开文件的更多控制选项。例如以下代码。
) ^5 L( i. Y* m6 B% a( e# l. V: b
% H3 G# `* d' Z0 n" U6 P/ w" i- l) x( W O/ y6 R0 i( N
6 ]& E. R" Q6 z3 x" ]* i& v! { C: ^$ {0 d" v
- FileStream fs=new FileStream(@“C:\1.txt”,FileMode.Append,FileAccess.Write);
6 o5 ]6 C# L9 f- b $ R3 O M8 h, t+ O
! I2 y J* t4 k, n3 u, N8 F% Y
+ d# J1 G* V8 h2 E0 D9 V9 C5 `& o9 x
8 k6 n; T! K% R
1 }7 V+ J' A4 \
7 v3 k. D9 p8 T- y" M% i5 X% i, |: U2 F/ V" E+ R" i
- StreamWriter sw=new StreamWriter(fs);
7 O- h- V+ G. D& [ 2 D1 I8 B* O& _ ]! g6 \! s
6 A3 N4 k; d2 t: s! T0 F" ?/ K
0 U& Q z5 l" u7 e3 N$ B: N
) s* ~7 t) f' u [% ?$ I# l
! N) K# E8 L: b0 EStreamWriter对象有两个方法来完成向文件或流中写入数据的功能。
: k% J8 \4 i. VWriteLine()方法:一次写入一行文本,流会自动把回车符合换行符添加到文本的末尾。
1 E B, v: q- L# G; OWrite()方法:向流或文件中写入文本,但不会在末尾添加回车和换行符。
% @: p/ E6 x; Q. D% {StreamWriter对象和FileStream对象一样,功能执行完毕后要使用Close()方法关闭以释放资源。
& f- g8 k3 f, i! ]: w2、StreamReader对象StreamReader对象用于读取文本文件。用某些方式构造StreamReader对象要比构造FileStream对象更简单,因为使用StreamReader时不需要FileStream的一些选项。特别是不需要模式和访问类型,因为它只能执行读取操作。2 V; `' L' I/ \% \) g5 P1 ^- w
StreamReader类的构造方法的版本比较多,最简单的构造函数只带一个文件名参数。4 q6 U7 ]5 L% ]! U. r+ Z: `7 j
StreamReader sr=new StreamReader(@“C:\test.txt”);1 ]3 d: [: ^$ K. I# p; i
StreamReader sr=new StreamReader(@“C:\test.txt”,Encoding.UTF8);
0 b: V# Y# o. e3 g7 b# x也可以把StreamReader关联到FileStream对象上。例如以下代码。& \1 v Q% C4 K. b# A0 d
FileStream fs=new FileStream(@ “C:\test.txt”,FileMode.Open,FileAccess.Read);
& C' |$ {. l5 `* \StreamReader sr=new StreamReader(fs);' L8 G e- Q2 m6 v. ~4 v$ `6 ^! r
StreamReader对象读取数据的方法主要有三个。9 v0 [( X! X/ P5 q) A* c
(1) Read()方法:此方法每次读取一个字符,返回的是代表这个字符的一个正数,当独到文件末尾时返回的是-1。/ O2 f7 e$ O6 M% F) z3 k; x
(2) ReadLine()方法:此方法每次读取流中的一行数据,但不包括回车和换行符。当读到文件末尾将返回null。
7 m+ D& W- o+ a5 u: Y% s' C& i1 n/ C(3) ReadToEnd()方法:此方法一次性读取文件中的所有数据。8 p& _, Z4 e/ p- G$ n
# \1 d& i" k) l) O: u
3、使用StreamWriter对象写入数据和StreamReader对象读取数据
x5 B7 V) \7 [5 f; a# k$ S3.1、StreamWriter对象写入数据
( b" C3 O3 `/ Q9 ^( t2 |8 B, J3 E6 O7 B, K. H5 ~
. ^' H3 l. e5 k5 }* s6 W
7 x' R( Q' A$ l- //读取数据
- private void button1_Click(object sender, EventArgs e)
- {
- //创建StreamReader对象
- //编码方式和写入数据时保持一致
- StreamReader sr = new StreamReader(@"C:\My Document\ReadMe1.txt", Encoding.Default);
- //利用StreamReader对象的ReadToEnd()方法读取文件中所有数据
- richTextBox1.Text = sr.ReadToEnd();
- //关闭StreamReader对象以释放资源
- sr.Close();
- }
6 r9 i. U/ c$ v3 ]9 j 9 n0 G& {9 k3 N! Z4 {+ i
+ s) ^1 f( g4 @- p' o
; b7 H7 F3 U7 @
( m7 q" d ]* M
4 y, y; q: c6 ]8 \* K B3.2、StreamReader对象读取数据# F& d$ y( P0 t i9 ?, J
* m/ V2 c' u8 A5 T& ~7 [' @5 e; Y
, p x+ P: j S5 A
2 C+ r3 s, N1 A# U A
- //写入数据
- private void button2_Click(object sender, EventArgs e)
- {
- //创建StreamWriter对象
- StreamWriter sw = new StreamWriter(@"C:\My Document\ReadMe1.txt", true, Encoding.Default);
- //获取输入数据的文件并放入数组
- string[] data = richTextBox1.Lines;
- //遍历字符串数组
- foreach (string line in richTextBox1.Lines)
- {
- //将文本通过StreamWriter对象逐行写入文件
- sw.WriteLine(line);
- }
- //关闭StreamWriter对象以释放资源
- sw.Close();
- }) Q1 M! t* B* h1 l5 i' n
$ k1 w9 O. u, b' \6 w. }
4 i* n1 a( y) |$ ~ n4 x0 ^8 N
& \9 |. D5 B5 V4 Y* _
$ c8 G/ J' s! x& N/ z四、总结 1、如果要对文件的内容进行读写,就需要用到流。! U' j! l. b" j, N- `
2、FileStream只能处理原始字节(Raw Byte)。处理原始字节的功能使FileStream类可以用于任何数据文件,而不仅仅是文本文件。通过读取字节数据,FileStream对象可以用于读取图像和声音的文件。这种灵活性的代价是,不能使用FileStream对象直接读入字符串,需要将字节数组转换为字符数组或者字符串。
# g- E$ A0 C5 y3 P( E. T! ? 3、虽然直接操作FileStream对象可以读取和显示文本文件,但是操作字节数组比较麻烦。如果知道某个文件包含文本,通常就可以使用StreamWriter和StreamReader类更方便的对这些文件进行写入和读,而不是FileStream对象。这是因为这些类工作的级别比较高,特别适合于读写文本。它们执行的方法可以根据流的内容,自动检测出停止读取文本较方便的位置。
; Y; a1 w' h6 q* E9 B; B5 F7 _: j/ z0 V$ E3 h" j
- r# V: s# C5 N1 o, u
7 S" c4 N5 i$ R, [8 C+ }% s; b/ O& W
6 O1 l8 m1 s& M
" H+ m* W$ I8 [: c' V s7 |: q2 b3 R; n4 ]' C
% k% X H. i* E( _4 H" u; d. j0 \* o
; O* s2 W- f+ @0 P) H: Z2 F. J L- K: p+ |
|
|