|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
文件流
, x" K# |% g% b3 Q) _) B5 c4 z' f% H, d, S S8 u) z/ B
一、流的概述
0 l3 C# c$ A4 r& V2 v* y5 |( ~ 要完成文件的读写操作,就必须了解C#中另外一个重要的概念——流(Stream)
0 t7 ?0 a& Z* |1 D2 D% `' O6 X C#中流的概念可以和生活中的流相对应。在生活中有水流和电流,首先要有一个源头,还需要有传输的管道,
! Z& {/ i3 S; B" F& C水流有河道、水管作为传输管道,电流有电线,而这些流都会有一个目的,就是它的流向。C#的流也需要源头——文件、数据流入流出管道以及数据的访问。' a# v# e6 O) `) w/ v
1、输出流和输入流 .Net Framework中进行的所有输入、输出工作都需要用到流。
# F6 `! k, M( H, Y4 S) d 1、输出流:当向某些外部目标写入数据时,就要用到输出流。. k5 @2 F" n5 e6 H: O3 A
2、输入流:用于将数据读到程序访问的内存或变量中。% e9 R4 t, A8 ]& ^, [
在程序的控制台中的可以理解为:* r9 e$ P! Z" k6 f, {* u
输出流:控制台程序中,将信息从程序中输出的处理:Console.WriteLine();
$ n: n6 R( U: I% r& @7 @1 V输入流:通过用户键盘来输入到程序当中处理:Console.ReadLine();
, N1 W- K$ g$ B/ L3 Q 2、文件读写,常用的三个类对于文件读写,常见的三个类:
" u( M& R& c$ K2 c8 O% r 1、FileStream(文件流):这个类主要用于在二进制文件中读写二进制数据——也可以使用它读写任何文件。. P0 D+ ?) s3 a( A$ m
2、StreamWriter(流写入器)和StreamReader(流读取器):这二个类是专门用来读写文本文件的。
' W! j7 J/ d+ I8 [" f r$ N2 _ D二、FileStream对象### 1、FileStream对象的二种重载 FileStream对象表示在磁盘或网络路径上指向文件的流。这个类提供了在文件中读写字节的方法。
" ]' s. r& R: V1 @- g; i; V8 U 有多种方法可以创建FileStream对象,FileStream类的构造函数有很多的重载版本,最简单的重载版本仅带有二个参数,即文件路径和FileModel枚举值。
* f# w6 M6 k9 H* m, `9 r& S1.1、第一种重载:& |8 S. i7 \6 @
+ q' D3 n& y+ G2 o
, D! s! H6 c/ J* ^9 b; j2 |
1 u' h$ a# k3 [2 A; y" ]- FileStream aFile = new FileStream( 文件路径 , FileMode.成员值);
, F& g$ S1 A% H% d, e9 z; S$ l/ ~
+ \2 p7 G; k& b% z+ k
1 c. i6 i" M$ G9 ^: @+ y, ~- R' }+ }9 u8 l! P- o, z
" @" k0 W6 B; rFileModel的枚举成员:
5 n6 M# Y$ Y+ V5 s& M4 @![]() 9 Z, t! p( i, W7 g- b& Q- O# ^
1.2、第二种重载:
9 n8 o8 P' s- }; L# v% r& H& f0 J* D1 P2 O
G! ~4 o2 T; C0 T; Q8 {
) H1 B3 }- }2 V8 ]% ?" V
- FileStream aFile = new FileStream( 文件路径, FileMode.成员值, FileAccess.成员值);
- H- a: P) K! D1 l$ w . R' b# P5 |: k
& X# i; x9 Y- @$ O$ A
" u7 X" @1 M% t6 ~- {5 Y5 p0 V; z* l
FileAccess的枚举成员:
) ]9 k# }2 W# m! O4 {) G% L& Q2 W# ~2 j% @7 j- u a3 Q
在FileAccess构造函数不使用FileAccess枚举参数的版本中,使用默认值FileAccess.ReadWrite。; {' m7 ~0 b; s6 g* f% k: p$ u2 x
File和FileInfo类中都提供了OpenRead()和OpenWrite()方法,使程序更易于创建FileStream对象。前者打 开了只读访问的文件,后者只允许写入文件。
) K m& m7 l D) J, V e# K 这些都提供了快捷方式,因此不一定要以FileStream构造函数的参数形式提供前面所有的信息。例如,下面的代码行打开了用于只读访问的Data.txt文件。
, a' g5 F) Y* U/ Q1 ]* W
/ u i' Z: g* J3 {0 C# F' S9 s* t! R; M' k. w
' W5 D4 B7 x5 l( u' J4 k
& _* ~: ~( i0 u7 n- FileStream aFile=File.OpenRead(@“C:\Data.txt”);$ ^5 }: R& u V
7 Q2 ^' f' j6 A* c. ?9 \5 O& M: Y$ u* q3 w( X4 f+ J* E; v+ ^
0 Y5 J- t+ h! o, ]& }
% E7 P5 _; r& f/ z
7 H% B, q1 K K. H) a7 }或者4 s6 u4 a! P) ?
1 _6 r% J5 |. Q( t! ?! w
& j/ e( \! p, m, ]5 v/ ?
7 j) W6 N. i9 X! d. {9 e3 `% c. X2 i4 H( b: [
- FileInfo aFileInfo=new FileInfo(@“C:\Data.txt”);
7 Q. J4 A8 x3 w' @/ \0 K) z. _, ^2 l$ P4 h ! H! c( R6 h% H: b
7 H' G) K: {' g; m H
6 w. z5 `' e" ?! v" I+ ?* Z g; r7 L
- U0 o" Y D, |
" o7 u! ~7 o6 i" U, h- q* r6 L i) d% K2 L
: Z- o) R5 \! V0 Y+ p' m- f2 B. j
' ?- y% r& e7 o/ }1 R/ u- FileStream aFile=afileInfo.OpenRead();
( h8 e% e, x* {2 a
% l7 W ]7 b% ?5 c3 I6 K+ E; b+ M( L1 o$ Y
- f$ d( y- n( L- ~/ B* D' c% B: \3 K# B8 @+ B
2、使用FileStream读取数据和写入数据 使用FileStream类读取数据并不容易,这是因为FileStream类只能处理原始字节(Raw Byte)。( L% W. L. h! x' v
FileStream对象的Read()方法是从FileStream对象所指向的文件访问数据的主要手段。这个方法从文件中读取数据,再把数据写入一个字节数组。
% W2 S6 H, B* w- y
6 C, m: F/ Q4 D' v8 C' I5 i 该方法有三个参数:第一个参数是传入的字节数组,用以接收FileStream对象中的数据。第二个参数是字节数组中开始写入数据的位置。通常是0,表示从数组开端开始放置读入的字节。最后一个参数指定从文件中读出多少字节。
1 k h. m/ u* ^6 ?' Z8 l( e1 S+ V1 v8 x, \& [) U
2.1、读取数据:
( X' v: G* R6 M! C. _3 j在编写程序代码前,需导入Sysytem.IO命名空间。此应用程序打开了磁盘上某个文件,用于读取其中的部分数据。首先,通过实例化一个FileStream的对象,将流指向这个文件。5 a* Z: M) Z( G0 P
这可以通过:
. R) Y1 H' e" O, Y0 n8 W
$ j7 V; J8 j& y& l3 A' f; L( d, [
# S& U( D' G' m4 b, F' y/ V
# X8 s3 b R1 ^% Z4 b" R
6 z5 |& S$ E- s- FileInfo aFileInfo =new FileInfo(@"C:\My Document\ReadMe1.txt");
- FileStream aFileInfo =aFileInfo.OpenRead();( w3 {' K' G' ?3 K- e2 ?
2 G; ?. L7 b9 V/ T# ?$ M& n8 t
3 l1 G& Q; b p& b( ?7 z! L2 Y
. J8 [: \: T' I: G. M- c8 f
步骤:创建FileStream对象,并指向文件流——得到文件大小(字节单位)——创建一个相同大小的字节数组——将文件的字节内容读到数组中——将数组中字节转为字符——输出显示——关闭流
8 c$ j! n. N' R; b
0 F/ o0 H7 E# t# @' C6 }/ u% `, E9 P+ }: `0 @- q) I
' W( L# H2 X& Y, A3 u3 a3 Z7 U
1 C; P& b8 Y: d0 F1 e- /// <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();
- }
# F9 C3 ]; L; h k . Z e: w; a( {' z2 r$ x& Q
# |- e4 p# C1 N
4 C5 V. X( R7 C/ l. \. U
6 O% L" u0 m' Q$ b9 [2.2、写入数据:$ \1 f# X1 S4 `1 k" {
步骤:创建FileStream对象,并指向文件流——声明一个数组是写入数据字节的2倍——使用Encoding类的GetBytes()方法将字符串中的一组字符编码到字节数组中,(1、编码的字符集的字符串,2、表明第一个编码的字符的索引,3、要编码的字符的数量,4、表明要包含所产生的字节序列的字节数组,5、开始写入所产生的字节序列索引位置)
' z" V. w3 w! P% u( T8 R
' ` b, N* V5 O" u0 }
. A2 y( }& \ x5 x1 ]% [* ?" X9 D" \9 u5 R8 g
+ d: L+ V) N+ v0 K. d
- /// <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();
- }
/ m& Z; b) @2 }* x3 k6 F % k' M* N# t8 o9 G) h: ]
! O3 a7 a- T( q8 ^% c
9 ~3 G; N7 n# X) R/ `. S4 A* N) P& M! K, I3 `( D" F/ d0 ?0 U
三、StreamWrite和StreamReader对象1、StreamWriter对象5 P/ W; [- a) ?; @
StreamWriter对象只能用于写入文件(或另一个流),StreamWriter类的构造方法有很多版本。最常用的有以下三种。& T& m& o: J6 }6 s
, p" p# L# ~) m- n7 P1 _. s" B' O
% n9 E: p& B `) y
5 w4 b0 A) M% H F
5 S" z1 Q6 N" S5 W) O0 e- StreamWriter sw=new StreamWriter(@ “C:\test.txt”);% Q3 I7 ~) k4 m$ i$ O! F" o: [
; O, |. i$ i7 ` ^
# Q0 v" Y9 @3 W: s" ~3 w
% |4 K4 l+ f' E$ ]
& @0 E8 P9 D6 ~将使用UTF-8的编码方式创建StreamWriter对象,.NET把这种编码设置为默认的编码方式。; W+ `; H. B' X1 J7 x& {
( v1 T. F$ k) Q+ B
7 O, j; a6 V! r7 p+ r* _3 g: @, @$ T$ w8 P- _7 a" w; Q2 k
+ N/ d v" ?1 [# L2 |7 x5 B
- StreamWriter sw=new StreamWriter(@ “C:\test.txt”, true);" L; X1 }/ ]- m1 K6 v# r
0 U8 O: v# @+ h! a% L5 G1 m" ?
8 l0 x; L3 }7 p4 V% Y" G7 v: ^) l7 n# |) D+ F9 P% {6 P
\) K0 h, e. Q6 b% N7 v2 G0 L* Y* A. f+ R5 q! [" U X6 ~( @* f
在这个构造函数中,第二个参数是bool类型,表示文件是否以追加的方式打开。
! K* |6 g1 R8 ]$ F- V$ J& H
' Y$ y3 v8 k/ d, k1 s7 b0 n" J) V# z! w' G0 p, _
/ {# {" }# Q3 \: ~( l" {5 q& B
( C/ n, @* \+ w5 M5 W8 b1 V! d2 r
- StreamWriter sw=new StreamWriter(@ “C:\test.txt”,true,Ecoding.ASCII);
6 Q9 j, ?3 E: W
/ r. h6 {) r' p3 S8 |( S% F7 `
; @& H$ i4 [, y: Z1 m7 F0 [0 r: e( J* n; x
: Y2 x7 s1 g6 f+ v. I
在第三个函数中,第三个参数可以指明要使用的编码方式ASCII来创建StreamWriter对象。但不能仅以文件名和编码方式来创建对象。
" F9 C* g9 d, C当然,也可以将StreamWriter关联到一个文件流上,以获得打开文件的更多控制选项。例如以下代码。
2 L9 X' ` g5 f |& J: J7 K5 g: f9 c) F1 U9 |/ J8 Y! X7 K6 m
' ^; t2 }7 G ?2 S3 v8 z8 g" M
( j3 N! n8 ~/ M+ A+ M. h! l% _1 u3 G
+ |/ B& c; _' R8 T& z# I- FileStream fs=new FileStream(@“C:\1.txt”,FileMode.Append,FileAccess.Write);3 |! {6 s9 O) J- k
. `6 b/ V1 N- f( F5 u: v
0 N. V1 @6 ~* W! _
0 a4 v4 N* b, T( k4 B) g
- [# |( M% n& I! S4 w
$ y1 w, \! F/ `+ W4 m: i/ ?" W: ~
/ I+ C! y$ o7 k: f
( s0 ]3 b5 p. @9 n& r+ |
- StreamWriter sw=new StreamWriter(fs);
$ {+ w% I" t0 J; O. H
. d' w" X5 p0 N4 Z( G2 K4 n; n" T+ e/ ?( q& R3 ~% o% T+ M
8 c% r9 [8 f3 I0 _( j
6 k! P3 c! b$ w8 M
# S' ], ^2 |& z7 {StreamWriter对象有两个方法来完成向文件或流中写入数据的功能。; E9 e- o# S3 c8 `* b
WriteLine()方法:一次写入一行文本,流会自动把回车符合换行符添加到文本的末尾。2 J3 l4 P) L; j' a; G
Write()方法:向流或文件中写入文本,但不会在末尾添加回车和换行符。* J7 X# A8 u+ D
StreamWriter对象和FileStream对象一样,功能执行完毕后要使用Close()方法关闭以释放资源。
1 N. [4 Y! C" k2、StreamReader对象StreamReader对象用于读取文本文件。用某些方式构造StreamReader对象要比构造FileStream对象更简单,因为使用StreamReader时不需要FileStream的一些选项。特别是不需要模式和访问类型,因为它只能执行读取操作。
/ P6 M2 E+ \ o# G- eStreamReader类的构造方法的版本比较多,最简单的构造函数只带一个文件名参数。
+ ~" ]: F. \% ]4 ^0 _StreamReader sr=new StreamReader(@“C:\test.txt”);/ @* `; b$ y( @0 x( i8 G$ O
StreamReader sr=new StreamReader(@“C:\test.txt”,Encoding.UTF8);
% N- c1 ?* Y+ Z# E2 {( ^6 l* }也可以把StreamReader关联到FileStream对象上。例如以下代码。, l8 V% q+ b2 |9 x @8 J4 s" S( {
FileStream fs=new FileStream(@ “C:\test.txt”,FileMode.Open,FileAccess.Read);
d f/ @' l2 A( c& y: w0 u" w# NStreamReader sr=new StreamReader(fs);
c# O7 A& Q8 r$ TStreamReader对象读取数据的方法主要有三个。
& N3 H: H: F# `(1) Read()方法:此方法每次读取一个字符,返回的是代表这个字符的一个正数,当独到文件末尾时返回的是-1。# g! b9 B4 q7 v7 }4 q6 R
(2) ReadLine()方法:此方法每次读取流中的一行数据,但不包括回车和换行符。当读到文件末尾将返回null。' p: c& p4 w+ _. ^' u0 t
(3) ReadToEnd()方法:此方法一次性读取文件中的所有数据。9 ~+ r: |, o8 L: U7 w# O7 H' k
* |* l) I: S% H5 p
3、使用StreamWriter对象写入数据和StreamReader对象读取数据
: z2 u7 L, C+ h$ W! `& Y3.1、StreamWriter对象写入数据$ j. J, f! m, m2 T0 F# q
* I7 g$ b$ |* _
3 ?" ? ~( O2 {3 r
" e! J) V {4 A: [) T, V: t- //读取数据
- 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();
- }; ?$ [* c4 E! ^, J+ D: x' W
/ J* t; E0 k& @
v- Z/ i# S/ Q M; }$ M- l0 Q) _
" h7 W/ ]: Y# m; G+ w' r9 ?0 @# N" ?4 p% I* l% _4 i
( \& M# B. G4 W* @
3.2、StreamReader对象读取数据
* h6 R0 L2 c, ]4 z, p! v- A% b9 k; I! n
: P2 S) B6 r; t2 V+ C" J
* ^8 C# z. B( w: }7 G1 q* w$ q- //写入数据
- 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();
- }) J5 b# k Y" ~' q
! c! n7 Q2 S# A t3 N
; Q! a& k, M+ @) d9 X/ f, u4 Y# t4 z( D$ P# o8 G* o& c3 q2 N1 ~; i& j
% v) M2 V _/ b* p2 S3 o
四、总结 1、如果要对文件的内容进行读写,就需要用到流。
0 m+ v" g, Q' m 2、FileStream只能处理原始字节(Raw Byte)。处理原始字节的功能使FileStream类可以用于任何数据文件,而不仅仅是文本文件。通过读取字节数据,FileStream对象可以用于读取图像和声音的文件。这种灵活性的代价是,不能使用FileStream对象直接读入字符串,需要将字节数组转换为字符数组或者字符串。
, a3 w3 F( J# L7 p% T 3、虽然直接操作FileStream对象可以读取和显示文本文件,但是操作字节数组比较麻烦。如果知道某个文件包含文本,通常就可以使用StreamWriter和StreamReader类更方便的对这些文件进行写入和读,而不是FileStream对象。这是因为这些类工作的级别比较高,特别适合于读写文本。它们执行的方法可以根据流的内容,自动检测出停止读取文本较方便的位置。) X* K( D0 h& {% a
8 ]4 X$ s1 F( V! a3 l% w i
0 h( |9 d$ n8 e* K+ ^. q4 b i9 \) Y( h
/ H! P; {3 `. Y4 s8 z
4 R. L. I" ]; r0 E/ R
6 a. ?; C5 Z' j4 u1 ]7 e7 a7 ^ y K4 M2 n( T
x6 f9 y4 `. W' t' A) R, ]
7 a: r5 u; J9 W, Z/ h3 J |
|