|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
文件流
) d% j; a2 D9 o$ S; a
# V7 m. \! M9 b% R$ b6 i一、流的概述2 T( @5 B9 ^ d" S* C9 N
要完成文件的读写操作,就必须了解C#中另外一个重要的概念——流(Stream). j2 k5 ]' Z5 a9 \
C#中流的概念可以和生活中的流相对应。在生活中有水流和电流,首先要有一个源头,还需要有传输的管道,
2 m; [* _) s# v) |0 m% P水流有河道、水管作为传输管道,电流有电线,而这些流都会有一个目的,就是它的流向。C#的流也需要源头——文件、数据流入流出管道以及数据的访问。, d4 h) t& D0 d& c0 P; I
1、输出流和输入流 .Net Framework中进行的所有输入、输出工作都需要用到流。
2 K, g2 C6 F) }- d6 z3 j 1、输出流:当向某些外部目标写入数据时,就要用到输出流。
' U2 Q' c% V: M# [6 U9 R/ g1 ] 2、输入流:用于将数据读到程序访问的内存或变量中。6 a5 B" n! }3 [, f
在程序的控制台中的可以理解为:+ r0 w! S" x6 d4 J- ^
输出流:控制台程序中,将信息从程序中输出的处理:Console.WriteLine();
" h/ |' p6 y6 F输入流:通过用户键盘来输入到程序当中处理:Console.ReadLine();5 w" y' K2 _6 Z/ }
2、文件读写,常用的三个类对于文件读写,常见的三个类:
) {: K6 \1 Z8 E% M 1、FileStream(文件流):这个类主要用于在二进制文件中读写二进制数据——也可以使用它读写任何文件。
8 f6 W+ f. s$ ~( Q3 ^- J1 h 2、StreamWriter(流写入器)和StreamReader(流读取器):这二个类是专门用来读写文本文件的。
. u0 I9 v3 n1 S二、FileStream对象### 1、FileStream对象的二种重载 FileStream对象表示在磁盘或网络路径上指向文件的流。这个类提供了在文件中读写字节的方法。
; n* s+ j8 f. I( R/ A& _ 有多种方法可以创建FileStream对象,FileStream类的构造函数有很多的重载版本,最简单的重载版本仅带有二个参数,即文件路径和FileModel枚举值。
: j) C: C4 n7 G. ?+ l5 F9 c1.1、第一种重载:
/ [ i3 U% D J" E- R1 S- |4 w) Q, M# k+ |" z
; N; v$ J, k2 {/ M% K
. a9 }3 M; _" n8 P6 k9 F$ {- FileStream aFile = new FileStream( 文件路径 , FileMode.成员值);
5 o. Y2 f, I5 p& ^( F. \7 ?
" C: _, I$ \" [" L, D3 q, l Z8 G3 c) h) S1 {
+ r7 _3 T* P1 |+ b4 ~6 q9 Z
) W2 u- m7 z5 w8 Q2 e: B% u% NFileModel的枚举成员: f! A. y8 X8 \" Z' E _
![]() : ^$ l' U: Z. E& U/ d4 \7 D
1.2、第二种重载:/ v$ Q. K8 m* [$ [5 z
6 ~9 z8 R0 a7 ^$ w3 t- T
f# f# w. p8 q7 j1 ~3 I: i
' C9 t N. e$ Q
- FileStream aFile = new FileStream( 文件路径, FileMode.成员值, FileAccess.成员值);( [- q; s. [) v- M. X6 i1 J7 u1 Y
0 P' b k* P) L3 ]. u& ~# Y
5 `' `( L# r! m2 T/ j1 I" t! S
1 n0 J2 n$ B! V1 W' o ~
( R% e$ O8 @# CFileAccess的枚举成员:
* ]/ `* N2 r& J) d) _/ o7 h" Y9 C- D5 K! T8 `0 i d# t
在FileAccess构造函数不使用FileAccess枚举参数的版本中,使用默认值FileAccess.ReadWrite。' g- K. F2 K, S' \0 M7 r
File和FileInfo类中都提供了OpenRead()和OpenWrite()方法,使程序更易于创建FileStream对象。前者打 开了只读访问的文件,后者只允许写入文件。0 S$ x: ^5 ]! z* W, j
这些都提供了快捷方式,因此不一定要以FileStream构造函数的参数形式提供前面所有的信息。例如,下面的代码行打开了用于只读访问的Data.txt文件。( S$ f" K6 N* q2 c
7 X$ y z( t4 U" L. t
3 N. E+ \+ C2 L# n& X2 X
- P. L& ~" U( _% ?/ g6 u9 d9 i
( Q) W2 \- \. \$ X0 V- FileStream aFile=File.OpenRead(@“C:\Data.txt”);
G0 z* d( o, e: q2 j+ D - s' o Q9 ` O& @% |- b
+ r; [5 V( B/ U+ B: L# V( T8 j. l }7 Z$ q, Y+ @
6 w7 F2 X' Y) `& _6 P
4 d% d* y6 }- y. x, \. E7 m或者8 D1 \& h# d$ B) d: b# J9 c
* x+ H3 _) c# l5 V$ h6 t
1 S f; }3 r X% t% ^
# n/ L: s3 [; W3 `3 h& k
$ Y# e8 T2 f5 x, E
- FileInfo aFileInfo=new FileInfo(@“C:\Data.txt”);
3 h5 a; `% n8 |2 G+ V 3 _- f, m4 r3 v6 C
* S n& t2 B+ _! \/ b7 w
+ D2 e8 o) ]/ D" W! c- J5 [' x( I% ?/ T, K9 Z& o- N! y
$ p7 S2 @' L) V# v& F3 v7 _2 W
! `8 T7 e+ P* A! |# P4 M
$ E! E1 u- h) h5 S( f, W, j T) @ e" J% v1 _
( t' h9 z4 ^0 B1 q
- FileStream aFile=afileInfo.OpenRead();
9 S5 q# z8 v6 P& v6 U
: C/ y" z( I% c; k
! T# `0 R- }( L" o+ I; r3 A2 O! B7 V' b0 i+ o1 a8 J
5 a! B8 \. n6 `0 B) U2、使用FileStream读取数据和写入数据 使用FileStream类读取数据并不容易,这是因为FileStream类只能处理原始字节(Raw Byte)。
( B: @" x& q# Q7 p; G FileStream对象的Read()方法是从FileStream对象所指向的文件访问数据的主要手段。这个方法从文件中读取数据,再把数据写入一个字节数组。# @4 W4 R# z& r$ @9 T
# H# k$ j% K9 H* z
该方法有三个参数:第一个参数是传入的字节数组,用以接收FileStream对象中的数据。第二个参数是字节数组中开始写入数据的位置。通常是0,表示从数组开端开始放置读入的字节。最后一个参数指定从文件中读出多少字节。7 Q/ h+ ]2 l+ d7 ] `# h
5 ^' }: u o# f2 i1 Z5 `& y2.1、读取数据:
0 [ a, X: I3 M/ |" U在编写程序代码前,需导入Sysytem.IO命名空间。此应用程序打开了磁盘上某个文件,用于读取其中的部分数据。首先,通过实例化一个FileStream的对象,将流指向这个文件。" [+ @, w& j/ @7 W1 y* o1 e
这可以通过:6 Y$ ]1 i2 w% Q. J9 E9 @
+ E% h! l6 I% L& j
1 S& I4 k+ m/ R. M2 p% |& M
" K/ k0 k6 h- K
0 w+ j& W3 v. T- FileInfo aFileInfo =new FileInfo(@"C:\My Document\ReadMe1.txt");
- FileStream aFileInfo =aFileInfo.OpenRead();
3 x2 {) A/ o) t0 ^ ! g8 g6 K* N* ?* D! l+ _% D9 U2 ?
, U& @3 b! q) R
& q+ q6 E" \6 f8 O* |( R, @' b* U) H9 p
步骤:创建FileStream对象,并指向文件流——得到文件大小(字节单位)——创建一个相同大小的字节数组——将文件的字节内容读到数组中——将数组中字节转为字符——输出显示——关闭流5 D- G1 n- a. K, Q) d. [
/ t+ S6 n; g6 `% w8 x% e6 O3 [3 ~ b% N) C
' j2 s2 g# r2 s; }$ h: L
7 |3 h, l" I' t4 V6 _/ u- /// <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();
- }0 u" O! \6 Z, O; ^! ]
, B$ ?6 t9 g* t
$ {( S; }; d$ u5 i9 Q" m/ d
% S9 J; q; g+ S. ]5 D! f+ k( @
/ w4 M! R Z8 r) r2.2、写入数据:
7 f& l4 Y e1 s步骤:创建FileStream对象,并指向文件流——声明一个数组是写入数据字节的2倍——使用Encoding类的GetBytes()方法将字符串中的一组字符编码到字节数组中,(1、编码的字符集的字符串,2、表明第一个编码的字符的索引,3、要编码的字符的数量,4、表明要包含所产生的字节序列的字节数组,5、开始写入所产生的字节序列索引位置)
2 H' u4 Y5 _0 R5 ~0 K* h/ }
! n/ r, Y( F: @9 k9 B" e( ^9 n' Q* h, L6 S" Q1 o! y3 |
1 W ?5 W* w) ?% s& @# R% m4 |% q4 m
4 T% B a1 A2 p- P+ O( A9 @. f
- /// <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();
- }8 G% `; ^- v2 U; \/ Z8 t. z
8 G4 Z8 @ B8 j% M- X& J7 U
: `5 ]6 w) J9 c! ?4 A4 c) Q$ j4 h
) k! y: v! z# {) _8 ]5 o' G三、StreamWrite和StreamReader对象1、StreamWriter对象4 n9 {1 Z6 `1 q4 O8 G
StreamWriter对象只能用于写入文件(或另一个流),StreamWriter类的构造方法有很多版本。最常用的有以下三种。
. P9 `" P# f2 i, O/ m
5 W/ P1 X9 Y( N4 l& G1 g% T# K3 \
. H* h8 G0 i/ g7 \ N" e, o* F& y! o1 [: Y M& o' h3 Q
/ D! j7 ?" _) u' o
- StreamWriter sw=new StreamWriter(@ “C:\test.txt”);4 ~6 w/ ?# y5 V; e
* H8 n; U; V3 W, m# x6 s
& x0 K) Y; K1 V- b- Y2 g
* \ E# C/ F, d* b& \% N7 R9 q
0 ^4 ^% e7 a7 j# l! ~' I将使用UTF-8的编码方式创建StreamWriter对象,.NET把这种编码设置为默认的编码方式。
- ~7 \% d( r4 c0 o& D8 c
) ^5 V5 D' ?3 q! K& v& r" F% [3 ~ Y# O, p5 V0 h# f z
; e6 A9 e8 j8 G0 X) C9 Y% G
+ V% A! b% G6 _8 i0 @) N2 b$ n- StreamWriter sw=new StreamWriter(@ “C:\test.txt”, true);+ F& ^$ _; J L9 d" X- h" r6 t
3 i/ }* R( z! f; c0 d1 O( ^8 ]- \( a
, o/ E" D' @5 o; G' [
5 b0 I- k a- V3 w
- g8 _3 T l) k在这个构造函数中,第二个参数是bool类型,表示文件是否以追加的方式打开。' N/ }4 ^' p# t
+ y. H8 c: X8 e! v' s
' x4 ~. r) J0 d z# h% ?- L! J& m& e4 T
/ T2 F2 I- f) v! l5 }+ n& M, O% q% d, A
- StreamWriter sw=new StreamWriter(@ “C:\test.txt”,true,Ecoding.ASCII);
, v) d0 {0 E' {! {9 q. r 6 S+ a8 ~3 r& U9 N/ B
# i) q8 S$ A" o# ]4 F
. T2 b. t7 Y3 L; K, u+ |$ |8 ~) k. j
( l4 G- T. n* H, i
, C1 D4 B( u) h, `在第三个函数中,第三个参数可以指明要使用的编码方式ASCII来创建StreamWriter对象。但不能仅以文件名和编码方式来创建对象。
$ U- o% D" D1 O" r* C- X当然,也可以将StreamWriter关联到一个文件流上,以获得打开文件的更多控制选项。例如以下代码。" n7 U0 z0 c2 A2 s- d. y2 b
8 y. O4 A' _) h3 U& J
7 B5 @1 T: [) A8 f" S
. A7 g, g, H7 {. e- `9 j5 z7 t
6 L) U$ {+ k2 n: T) a+ c6 @# ` h
- FileStream fs=new FileStream(@“C:\1.txt”,FileMode.Append,FileAccess.Write);
8 I' N, D) T1 L3 c9 F( Z 5 q: \/ E$ t% j N/ e+ n& l
& m U: t' P2 X& ~2 V k
* w) a& h9 a! ~/ `8 m5 g
1 B/ G5 n3 c# k% o3 U$ ~( f
9 u0 ^3 ?5 ?' F! q' ^1 V# x8 @0 d& ]
* [/ Y( ~( }. L* K
5 V2 L" Q: B F$ \" L4 K, {
* x) o2 Z" K/ m2 q5 Y( {9 }- StreamWriter sw=new StreamWriter(fs);
9 c0 B9 O: I$ M/ ~, I9 b+ _ 1 {4 F$ o, q2 O0 e- C
1 X) {4 y; [# x5 I+ i$ t B2 ]' a3 e4 _% s/ Q
p K$ E% W* T2 i+ @5 F O% {9 x: _' F3 U
StreamWriter对象有两个方法来完成向文件或流中写入数据的功能。 V; e: Q1 X; O% c
WriteLine()方法:一次写入一行文本,流会自动把回车符合换行符添加到文本的末尾。
; P- o) N% r, U: G1 p% L; kWrite()方法:向流或文件中写入文本,但不会在末尾添加回车和换行符。" S; x H# F$ [
StreamWriter对象和FileStream对象一样,功能执行完毕后要使用Close()方法关闭以释放资源。
5 n' Y+ V$ ]+ {2、StreamReader对象StreamReader对象用于读取文本文件。用某些方式构造StreamReader对象要比构造FileStream对象更简单,因为使用StreamReader时不需要FileStream的一些选项。特别是不需要模式和访问类型,因为它只能执行读取操作。
9 I& ?1 J% X; m! \StreamReader类的构造方法的版本比较多,最简单的构造函数只带一个文件名参数。: }, S9 T5 w: @; b) K
StreamReader sr=new StreamReader(@“C:\test.txt”);. e; {# M! s+ d, t& s
StreamReader sr=new StreamReader(@“C:\test.txt”,Encoding.UTF8);
k% V( v# r0 Y) ^" B也可以把StreamReader关联到FileStream对象上。例如以下代码。7 x j/ T; T7 w
FileStream fs=new FileStream(@ “C:\test.txt”,FileMode.Open,FileAccess.Read);, O/ Q4 \0 ?3 y
StreamReader sr=new StreamReader(fs);( p) E3 o+ P- E. N, Q9 Y
StreamReader对象读取数据的方法主要有三个。
7 B1 j$ r0 e% a/ l(1) Read()方法:此方法每次读取一个字符,返回的是代表这个字符的一个正数,当独到文件末尾时返回的是-1。" M r. a7 X2 j- n
(2) ReadLine()方法:此方法每次读取流中的一行数据,但不包括回车和换行符。当读到文件末尾将返回null。
- p$ x! `' D/ h8 a5 U(3) ReadToEnd()方法:此方法一次性读取文件中的所有数据。7 ?$ e8 ~' l) |; a
1 Y$ }+ ^0 M/ G4 p3、使用StreamWriter对象写入数据和StreamReader对象读取数据
* L" K. M# _! h) m3 n3.1、StreamWriter对象写入数据% R3 i) j3 X3 m% s
6 } k# o9 D8 e2 D2 u, p/ S2 Q g+ X2 u8 ^
! o, U2 J/ G9 H# ]* h4 }7 S
- //读取数据
- 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();
- }$ o8 f) K3 F/ \/ i v& x
% D& r$ ~$ k- v3 r6 o3 c1 }
% T- l( N, M/ U( g0 \5 t# w Z3 ^: V
. c3 s! N2 t2 f! s: o
$ A- o! f3 e$ x. y$ x& g, b3.2、StreamReader对象读取数据
, I+ @) D m: c$ Y ?/ O0 T9 { a# u
3 ~. Y; c) N9 r, b) O, A
4 y) z9 l4 b& c
- //写入数据
- 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();
- }
% a9 Y% K/ P2 q: D
4 F( Q" V7 H6 F6 R
7 `' s# x* w0 h( |, D5 p! H, K, m# P2 m) w( k( u; @9 O4 w
# Y. s* U* K3 U F# y) d
四、总结 1、如果要对文件的内容进行读写,就需要用到流。9 N% M3 C$ n& }! U/ p: t
2、FileStream只能处理原始字节(Raw Byte)。处理原始字节的功能使FileStream类可以用于任何数据文件,而不仅仅是文本文件。通过读取字节数据,FileStream对象可以用于读取图像和声音的文件。这种灵活性的代价是,不能使用FileStream对象直接读入字符串,需要将字节数组转换为字符数组或者字符串。: F5 S D9 {8 C8 I% Y" Y
3、虽然直接操作FileStream对象可以读取和显示文本文件,但是操作字节数组比较麻烦。如果知道某个文件包含文本,通常就可以使用StreamWriter和StreamReader类更方便的对这些文件进行写入和读,而不是FileStream对象。这是因为这些类工作的级别比较高,特别适合于读写文本。它们执行的方法可以根据流的内容,自动检测出停止读取文本较方便的位置。
+ O2 Z/ _4 J+ M9 h% j; Y8 v9 Y, K/ ^7 O9 v
2 ]: h8 H* U$ l+ A5 `9 I: d6 b# {
6 z8 {6 ~- l( S4 Z% Q
4 I0 _8 o' r% E* I6 w5 H
3 A/ s8 U( f& {
; J% P) e& @ }* t3 J, d/ p' Q: Q. b( [6 M S- A
# K. y6 H9 M/ l: p
- F$ F! a% [7 N3 p% p+ K7 q |
|