本文主要讲解一下在文件的读取中,StreamWriter、StreamReader和FileStream分别有什么样的不同,废话少说,直接进入主题。
下面是关于StreadReader的使用例子。
完整代码如下:
引入命名空间:
using System.IO;
完整代码:
namespace StreamReaderApp { class Program { static void Main(string[] args) { string s = ""; using (StreamReader sr = new StreamReader("c:\\file1.txt")) { s = sr.ReadToEnd(); } Console.WriteLine(s); Console.ReadLine(); } } }
一、StreamReader类的介绍
构造函数:
StreamReader sw = new StreamReader(Stream stream); StreamReader sw = new StreamReader(string path);
为指定的流/文件名初始化 StreamReader 类的新实例,并且使用默认的编码(UTF-8)读取文件。默认的编码方式是UTF-8,Encoding.Default表示的编码方式也是UTF-8
StreamReader sw = new StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks); StreamReader sw = new StreamReader(string path, bool detectEncodingFromByteOrderMarks);
用指定的字节顺序(BOM)标记检测选项,为指定的流/文件名初始化 StreamReader 类的一个新实例。其中detectEncodingFromByteOrderMarks是用来表示是否自动探测BOM(文件前端标识文字编码的字节)。
StreamReader sw = new StreamReader(Stream stream, Encoding encoding); StreamReader sw = new StreamReader(string path, Encoding encoding);
用指定的字符编码为指定的流/文件名初始化 StreamReader 类的一个新实例,因为有些编码(如GB2312、UTF7)就没有BOM,就认不到编码,就需要手动指定一个编码。
StreamReader sw = new StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks); StreamReader sw = new StreamReader(string path, Encoding encoding, bool detectEncodingFromByteOrderMarks);
为指定的流/文件名初始化 StreamReader 类的新实例,带有指定的字符编码和字节顺序标记检测选项。
StreamReader sw = new StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks, int bufferSize); StreamReader sw = new StreamReader(string path, bool detectEncodingFromByteOrderMarks, int bufferSize);
为指定的流/文件名初始化 StreamReader 类的新实例,带有指定的字符编码、字节顺序标记检测选项和缓冲区大小。
常用方法及属性:
Read() // 单字符读入(文件指针不移动)
1、public override int Read(); //读取输入流中的下一个字符并使该字符的位置提升一个字符,返回的是字符的十进制值。
StreamReader sr = new StreamReader(@"D:\Readme.txt", Encoding.GetEncoding("GB2312")); //通常需要转码为GB2312 int Ichar = 0; while ((Ichar = sr.Read()) != -1) // 不再有可用的字符,则为 -1 { MessageBox.Show(Convert.ToChar(Ichar).ToString()); //将int类型转成ASCII字符 }
2、public override int Read(char[] buffer, int index, int count); //从当前流中将最多的 count 个字符读入到buffer数组中,从buffer数组从index位开始写入,返回值为读取
的字符总数。
char[] buffer = new char[512]; int readCount = sr.Read(buffer, 0, 512); for (int i = 0; i<readCount; i++) { MessageBox.Show(buffer[i].ToString()); }
ReadLine() // 行读入
方法原型:public override string ReadLine() // 输入流中的下一行;如果到达了输入流的末尾,则为空引用
string strLine = null; while ((strLine = sr.ReadLine()) != null) { MessageBox.Show(strLine); }
ReadToEnd() // 从流的当前位置到末尾读取流。
方法原型:public override string ReadToEnd(); // 如果当前位置位于流的末尾,则返回空字符串 ("")。
备注:用该方法可以把数据流一次性全部加载到内存中,内存中数据的操作的速度是非常快的,但要注意的是,如果文件太大的话,可能内存会不够,就用Read或ReadLine()方法读取。
string strLine = sr.ReadToEnd(); MessageBox.Show(strLine);
Peek() //读取下 一个字符,但位置不移动
方法原型:public override int Peek()
while (sr.Peek() != -1) { MessageBox.Show(sr.ReadLine()); }
EndOfStream // 获取一个值,该值表示当前的流位置是否在流的末尾
while (!sr.EndOfStream) { MessageBox.Show(sr.ReadLine()); }
CurrentEncoding // 获取当前 StreamReader 对象正在使用的当前字符编码
MessageBox.Show(sr.CurrentEncoding.EncodingName);
BaseStream // 返回基础流
二、StreamWriter类的介绍
构造函数:
StreamWriter sw = new StreamWriter(Stream stream); StreamWriter sw = new StreamWriter(string path);
用UTF-8编码及默认缓冲区大小,为指定的流/文件初始化StreamWriter类的一个新实例。
StreamWriter sw = new StreamWriter(Stream stream,Encoding encoding);
用指定的编码及默认缓冲区大小,为指定的流初始化StreamWriter类的新实例。(默认写入编码为UTF8)
StreamWriter sw = new StreamWriter(string path, bool append);
使用默认编码和缓冲区大小,为指定路径上的指定文件初始化 StreamWriter 类的新实例。true表示如果该文件存在,则可以向其追加。false表示将其全部重写。如果该文件
不存在,则此构造函数将创建一个新文件。
StreamWriter sw = new StreamWriter(Stream stream,Encoding encoding,int bufferSize);
用指定的编码及缓冲区大小,为指定的流初始化 StreamWriter 类的新实例。int为缓冲区大小
StreamWriter sw = new StreamWriter(string path, bool append,Encoding encoding);
使用指定编码和默认缓冲区大小,为指定路径上的指定文件初始化 StreamWriter 类的新实例。true表示如果该文件存在, 则可以向其追加。false表示将其全部重写。如果该文件不存在,则此构造函数将创建一个新文件。
StreamWriter sw = new StreamWriter(string path,bool append,Encoding encoding,int bufferSize);
使用指定编码和缓冲区大小,为指定路径上的指定文件初始化 StreamWriter 类的新实例。true表示如果该文件存在,则可以向其追加。false表示将其全部重写。如果该文件不存在,则此构造函数将创建一个新文件。
常用方法及属性:
Write() // 写入流。(该方法有17种重载方法,就不一一解说,讲几个常用的方法)
1、public override void Write(string value) //将字符串写入流。
StreamWriter sw = new StreamWriter(@"D:\a.txt", true); //true表示如果a.txt文件已存在,则以追加的方式写入 sw.Write(this.textBox1.Text); sw.Close();
2、public override void Write(char value) // 按字符写入
char[] charArray = new char[] { 'a', 'b', 'c', 'd', 'e', 'f' }; for (int i = 0; i<charArray.Length; i++) { sw.Write(charArray[i]); }
3、public override void Write(char[] buffer) // 按字符数组写入
char[] charArray = new char[] { 'a', 'b', 'c', 'd', 'e', 'g' }; sw.Write(charArray);
4、public virtual void Write(string format, params Object[] arg) //按指定格式转换的字符串写入
sw.Write("我的期待月薪为{0,9:C4},实现年龄为{1,9},成功率{2,9:P2}", new Object[]{ 20000, 30, 1 });
运行结果:我的期待月薪为¥20,000.0000,实现年龄为 30,成功率 100.00% ,具体请参考stringFormat语法
5 、public override void Write(char[] buffer, int index, int count) // 从buffer数组的第index开始写入count个字符
char[] charArray = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g' }; sw.Write(charArray , 3, 4); 运行结果:defg
WriteLine() // 写入流,后跟行结束符(行结束符样式可用NewLine属性设置)。(该方法有18种重载方法,只讲常用的)
1、public virtual void WriteLine() //写入空行,等同于跳到下一行
sw.WriteLine();
2、public virtual void WriteLine(char value)
3、public virtual void WriteLine(char[] buffer)
4、public virtual void WriteLine(string value)
5、public virtual void WriteLine(string format, params Object[] arg)
6、public virtual void WriteLine(char[] buffer, int index, int count)
7、public virtual void WriteLine(Object value)
Flush // 清理当前编写器的所有缓冲区,并使所有缓冲数据写入基础流。
方法原型:public override void Flush()
属性:
AutoFlush // 设置StreamWriter 是否在每次调用 StreamWriter.Write 之后,将其缓冲区刷新到基础流。
备注:除非我们显示地调用Flush 或 Close,否则,刷新流不会刷新其基础编码器,也就是不会写入到硬盘中,将 AutoFlush 设置为 true后只要调用write()方法会
自动将数据写入到硬盘中,如果用户期望您所写入的设备能够立即反馈,则将 AutoFlush 设置为 true。
Encoding // 获取将输出写入到其中的 Encoding。
MessageBox.Show(sw.Encoding.EncodingName);
NewLine // 设置由当前 TextWriter 使用的行结束符字符串样式
sw.NewLine = "\t"; sw.WriteLine("aaa"); sw.WriteLine("bbb"); 运行结果:“aaa bbb ”
BaseStream //获取同后备存储区连接的基础流。
三、FileStream类的介绍
FileStream(String, FileMode) // 使用指定的路径和创建模式初始化 FileStream 类的新实例。
函数原型:public FileStream(string path, FileMode mode)
FileMode成员:
(1)Append 打开现有文件并查找到文件尾,或创建新文件。FileMode.Append 只能同 FileAccess.Write 一起使用。
(2)Create 创建新文件(如果文件不存在)。如果文件已存在,它将被改写。这要求 FileIOPermissionAccess.Write。FileMode.Create 等效于这样的 请求:如果文件不存在,则使用 CreateNew;否则使用 Truncate。
(3)CreateNew 创建新文件。此操作需要 FileIOPermissionAccess.Write 。如果文件已存在,则将引发 IOException。
(4)Open 打开现有文件。打开文件的能力取决于 FileAccess 所指定的值。如果该文件不存在,则引发 System.IO.FileNotFoundException。
(5)OpenOrCreate 打开文件(如果文件存在);否则,创建新文件。如果用 FileAccess.Read 打开文件,则需FileIOPermissionAccess.Read。
(6)Truncate 打开现有文件。文件一旦打开就将被截断为零字节大小。此操作需要FileIOPermissionAccess.Write。试图从使用Truncate 打开的文件中进行读取将导致异常。
FileStream fs = new FileStream(@"D:\a.txt", FileMode.Create);
FileStream(String, FileMode, FileAccess) // 使用指定的路径、创建模式和读/写权限初始化 FileStream 类的新实例。
函数原型:public FileStream(string path, FileMode mode, FileAccess access)
FileAccess成员:
(1)Read 对文件的读访问。可从文件中读取数据。同 Write 组合即构成读写访问权。
(2)ReadWrite 对文件的读访问和写访问。可从文件读取数据和将数据写入文件。
(3)Write 文件的写访问。可将数据写入文件。同 Read 组合即构成读/写访问权。
FileStream fs = new FileStream(@"D:<span style="font-size:12px;">\a.txt", FileMode.Create, FileAccess.ReadWrite);
FileStream(String, FileMode, FileAccess, FileShare) // 使用指定的路径、创建模式、读/写权限和共享权限创建 FileStream 类的新实例。
函数原型:public FileStream(string path, FileMode mode, FileAccess access, FileShare share)
FileShare成员:
(1)Delete 允许随后删除文件(在一个进程进行读取某文件时,另一个进程可以同时对该文件进行删除)。
(2)Inheritable 使文件句柄可由子进程继承。Win32 不直接支持此功能。
(3)None 谢绝共享当前文件。文件关闭前,打开该文件的任何请求(由此进程或另一进程发出的请求)都将失败。
(4)Read 允许随后打开文件读取。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取的请求(由此进程或另一进程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
(5)ReadWrite 允许随后打开文件读取或写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行读取或写入的请求(由此进程或另一进程发出)都将失败。 但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
(6)Write 允许随后打开文件写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行写入的请求(由此进程或另一进过程发出的请求)都将失败。但是,即使指定了此标志,仍可能需要附加权限才能够访问该文件。
FileStream fs = new FileStream(@"D:\a.txt",FileMode.Create,FileAccess.ReadWrite,FileShare.ReadWrite);
FileStream (String, FileMode, FileAccess, FileShare, Int32) 用指定的路径、创建模式、读/写及共享权限和缓冲区大小初始化 FileStream 类的新实例。
函数原型:public FileStream (string path,FileMode mode,FileAccess access,FileShare share,int bufferSize)
FileStream fs = new FileStream(@"D:\a.txt",FileMode.Create,FileAccess.ReadWrite,FileShare.ReadWrite,512);
FileStream (String, FileMode, FileAccess, FileShare, Int32, Boolean) // 使用指定的路径、创建模式、读/写和共享权限、缓冲区大小和同步或异步状态初始化FileStream 类的新实例。
函数原型:public FileStream (string path,FileMode mode,FileAccess access,FileShare share,int bufferSize,bool useAsync) // userAsyn 指定使用异步 I/O 还是同步 I/O。
备注:当异步打开时,BeginRead 和 BeginWrite 方法在执行大量读或写时效果更好,但对于少量的读/写,这些方法速度可能要慢得多。正确使用异步 I/O,可以使应用程序的速度加快 10 倍,但是如果在没有为异步 I/O 重新设计应用程序的情况下使用异步 I/O,则可能使性能降低 10 倍。
FileStream fs = new FileStream(@"D:\a.txt",FileMode.Create,FileAccess.ReadWrite,FileShare.ReadWrite,512 ,true);
FileStream (String, FileMode, FileAccess, FileShare, Int32, FileOptions) // 使用指定的路径、创建模式、读/写和共享权限、其它FileStreams 可以具有的对此 文件的访问权限、缓冲区大小和附加文件选项初始化 FileStream 类的新实例。
函数原型:public FileStream (string path,FileMode mode,FileAccess access,FileShare share,int bufferSize,FileOptions options)
FileOptions 成员:
(1)Asynchronous 指示文件可用于异步读取和写入。
(2)DeleteOnClose 指示当不再使用某个文件时,自动删除该文件。
(3)Encrypted 指示文件是加密的,只能通过用于加密的同一用户帐户来解密。
(4)None 指示无其他参数。
(5)RandomAccess 指示随机访问文件。系统可将此选项用作优化文件缓存的提示。
(6)SequentialScan 指示按从头到尾的顺序访问文件。系统可将此选项用作优化文件缓存的提示。如果应用程序移动用于随机访问的文件指针,
可能不发生优化缓存,但仍然保证操作的正确性。 指定此标志可以提高使用顺序访问读取大文件的应用程序的性能。对于
大多数情况下都按顺序读取大文件、但偶尔跳过小的字节范围的应用程序而言,性能提升可能更明显。
(7)WriteThrough 指示系统应通过任何中间缓存、直接写入磁盘。
FileStream fs = new FileStream(@"D:\a.txt",FileMode.Create,FileAccess.ReadWrite,FileShare.ReadWrite,512 ,FileOptions.Asynchronous);
FileStream (String, FileMode, FileSystemRights, FileShare, Int32, FileOptions) 使用指定的路径、创建模式、访问权限和共享权限、缓冲区大小和附加文件选
项初始化 FileStream 类的新实例。
函数原型:public FileStream (string path,FileMode mode,FileSystemRights rights,FileShare share,int bufferSize,FileOptions options)
FileSystemRights成员:(访问权限)
AppendData 指定将数据追加到文件末尾的权限。
ChangePermissions 指定更改与文件或文件夹关联的安全和审核规则的权限。
CreateDirectories 指定创建文件夹的权限。此权限需要 Synchronize 值。请注意,如果在创建文件或文件夹时未显式设置 Synchronize 值,则会自动为您设置 Synchronize 值。
CreateFiles 指定创建文件的权限。此权限需要Synchronize值。请注意,如果在创建文件或文件夹时未显式设置Synchronize 值,则会自动为您设置Synchronize值。
Delete 指定删除文件夹或文件的权限。
DeleteSubdirectoriesAndFiles 指定删除文件夹和该文件夹中包含的所有文件的权限。
ExecuteFile 指定运行应用程序文件的权限。
FullControl 指定对文件夹或文件进行完全控制以及修改访问控制和审核规则的权限。此值表示对文件进行任何操作的权限,并且是此枚举中的所有权限的组合。
ListDirectory 指定读取目录内容的权限。
Modify 指定读、写、列出文件夹内容、删除文件夹和文件以及运行应用程序文件的权限。此权限包括ReadAndExecute权限、Write权限和Delete权限。
Read 指定以只读方式打开和复制文件夹或文件的权限。此权限包括ReadData权限、
ReadExtendedAttributes 权限、ReadAttributes权限和ReadPermissions 权限。
ReadAndExecute 指定以只读方式打开和复制文件夹或文件以及运行应用程序文件的权限。此权限包括 Read 权限和 ExecuteFile 权限。
ReadAttributes 指定从文件夹或文件打开和复制文件系统属性的权限。例如,此值指定查看文件创建日期或修改日期的权限。这不包括读取数据、 扩展文件系统属性或访问和审核规则的权限。
ReadData 指定打开和复制文件或文件夹的权限。这不包括读取文件系统属性、扩展文件系统属性或访问和审核规则的权限。
ReadExtendedAttributes 指定从文件夹或文件打开和复制扩展文件系统属性的权限。例如,此值指定查看作者和内容信息的权限。这不包括读取数据、文件系统属性或访问和审核规则的权限。
ReadPermissions 指定从文件夹或文件打开和复制访问和审核规则的权限。这不包括读取数据、文件系统属性或扩展文件系统属性的权限。
Synchronize 指定应用程序是否能够等待文件句柄,以便与 I/O 操作的完成保持同步。
Synchronize 值在允许访问时自动被设置,而在拒绝访问时自动被排除。创建文件或文件夹的权限需要此值。请注意,如果在创建文件时未显式设置此值,
则会自动为您设置此值。
TakeOwnership 指定更改文件夹或文件的所有者的权限。请注意:资源的所有者对该资源拥有完全权限。
Traverse 指定列出文件夹的内容以及运行该文件夹中所包含的应用程序的权限。
Write 指定创建文件夹和文件以及向文件添加数据或从文件移除数据的权限。此权限包括
WriteData 权限、AppendData 权限、WriteExtendedAttributes 权限和 WriteAttributes 权限。
WriteAttributes 指定打开文件系统属性以及将文件系统属性写入文件夹或文件的权限。这不包括写入数据、扩展属性以及写入访问和审核规则的功能。
WriteData 指定打开和写入文件或文件夹的权限。这不包括打开和写入文件系统属性、扩展文件系统属性或访问和审核规则的权限。
WriteExtendedAttributes 指定打开文件夹或文件的扩展文件系统属性以及将扩展文件系统属性写入文件夹或文件的权限。这不包括写入数据、属性或访问和审
<span style="white-space:pre;"> </span> 核规则的功能。
方法
Read() //从流中读取字节块并将该数据写入给定缓冲区中。
函数原型:public override int Read (byte[] array,int offset,int count) // 从byte数组的offset位开始写入count个字节
备注:因为FileStream主要用于读取字节和字节数组,也就是二进制数据,所以它不能指定编码格式,但是如果我们用它来读取有中文的文本的话,我们就会发现它会乱码,
因为默认的编码是UTF8,所以我们必须用System.Text.Encoding.GetEncoding("GB2312").GetChars()进行转码,这样很麻烦,所以我们通常不用FileStream读写有中文
的文本。
byte[] byteArray = new byte[512]; char[] charArray = new char[512]; int byteCount = fs.Read(byteArray, 0, 512); System.Text.Encoding.GetEncoding("GB2312").GetChars(byteArray,0,byteCount,charArray,0); for (int i = 0; i < byteCount; i++) { <span style="white-space:pre;"> </span>MessageBox.Show(charArray[i].ToString()); }
ReadByte() // 从文件中读取一个字节,并将读取位置提升一个字节。(没法读取中文)
函数原型:public override int ReadByte () //返回的字符的ASCII的十进制数,流的末尾读取则为 -1
int b = 0; while((b = fs.ReadByte())!=-1) { <span style="white-space:pre;"> </span>MessageBox.Show(Convert.ToChar(b).ToString()); }
Seek() // 将该流的当前位置设置为给定值。
函数原型:public override long Seek (long offset,SeekOrigin origin) //相对于origin 的点,从此偏移offset个字节处开始查找。(按字节偏移的,而不是字符)
SeekOrigin成员:
(1)Begin 指定流的开头。
(2)Current 指定流内的当前位置。
(3)End 指定流的结尾。
int b = 0; fs.Seek(2, SeekOrigin.Begin); //文件指针偏移到第2个字节 b = fs.ReadByte(); MessageBox.Show(Convert.ToChar(b).ToString()); fs.Seek(-3, SeekOrigin.End); //文件指针从文件末尾往回偏移3个字节 b = fs.ReadByte(); MessageBox.Show(Convert.ToChar(b).ToString());
假设文件的内容是:abcdefghijk 那结果就是:c 和 j
Write() //使用从缓冲区读取的数据将字节块写入该流。
函数原型:public override void Write (byte[] array,int offset,int count) // 将字节数组从offset位开始写入count个字节
byte[] byteArray = new byte[] { 97,98,99,100,110,120}; //字节数组 fs.Write(byteArray, 0, byteArray.Length); 运行结果:abcdnx
WriteByte() //将一个字节写入文件流的当前位置。
函数原型:public override void WriteByte (byte value)
byte b = 97;
fs.WriteByte(b);
BeginRead() // 开始异步读。 (需要设置FileOptions.Asynchronous参数才能进行异步操作)
函数原型:public override IAsyncResult BeginRead (byte[] array,int offset,int numBytes,AsyncCallback userCallback,Object stateObject)
参数:numBytes 表示最多读取的字节数。
userCallback 异步读操作完成后调用的方法。
stateObject 一个用户提供的对象,它将该特定的异步读取请求与其他请求区别开来。
备注:调用BeginRead/BeginWrite/EndRead/EndWrite执行异步时需要在创建FileStream时传入FileOptions.Asynchronous参数才能获取真正的IOCP支持,否则BeginXXX方法将会使用默认定义在Stream基类上的实现。Stream基类中BeginXXX方法会使用委托的BeginInvoke方法来发起异步调用——这会使用一个额外的线程来执行任务。虽然当前调用线程立即返回了,但是数据的读取或写入操作依旧占用着另一个线程(IOCP支持的异步操作时不需要线程的),因此并没有任何“节省”,反而还很有可能降低了应用程序的性能,因为额外的线程切换会造成性能损失。
EndRead() // 等待挂起的异步读取完成。(需要设置FileOptions.Asynchronous参数才能进行异步操作)
函数原型:public override int EndRead (IAsyncResult asyncResult)
参数:asyncResult 对所等待的挂起异步请求的引用。
BeginWrite() // 开始异步写。(需要设置FileOptions.Asynchronous参数才能进行异步操作)
函数原型:public override IAsyncResult BeginWrite (byte[] array,int offset,int numBytes,AsyncCallback userCallback,Object stateObject)
EndWrite() // 结束异步写入,在 I/O 操作完成之前一直阻止。(需要设置FileOptions.Asynchronous参数才能进行异步操作)
函数原型:public override void EndWrite (IAsyncResult asyncResult)
Flush() // 清除该流的所有缓冲区,使得所有缓冲的数据都被写入到基础设备。
函数原型:public override void Flush ()
属性:
Name // 获取操作的文件完整地址。
Length // 获取整个文件用字节表示的流长度。 (一个中文占2个字节)
Position // 获取或设置此流的当前位置。
CanRead // 获取当前流是否支持读取。(如果该流已关闭或是通过只写访问方式打开的,则返回false,调用Read、ReadByte 和 BeginRead 方法将引发 NotSupportedException。)
CanSeek // 获取当前流是否支持查找。(如果该流已关闭或是通过只写访问方式打开的,则返回false,调用 Length、SetLength、Position 和 Seek 方法将引发 NotSupportedException。)
CanWrite // 获取当前流是否支持写入。(如果该流已关闭或是通过只写访问方式打开的,则返回false,调用 SetLength、Write、BeginWrite 或 WriteByte 方法将引发 NotSupportedException。)
IsAsync // 获取FileStream 是否异步打开的。
Handle // 获取当前 FileStream 对象所封装文件的操作系统文件句柄。
SafeFileHandle // 获取 SafeFileHandle 对象,该对象表示当前 FileStream 对象封装的文件的操作系统文件句柄。
四、StreamReader/StreamWriter与FileStream的区别
FileStream对象表示在磁盘或网络路径上指向文件的流。这个类提供了在文件中读写字节的方法,但经常使用StreamReader或 StreamWriter执行这些功能。这是因为FileStream类操作的是字节和字节数组,而Stream类操作的是字符数据。这是这两种类的一个重要区别,如果你是准备读取byte数据的话,用StreamReader读取然后用 System.Text.Encoding.Default.GetBytes转化的话,如下,则可能出现数据丢失的情况,如byte数据的个数不对等。因此操作byte数据时要用FileStream。 string textContent = fileStream.ReadToEnd();byte[] bytes = System.Text.Encoding.Default.GetBytes(textContent);
字符数据易于使用, 但是有些操作,比如随机文件访问(访问文件中间某点的数据),就必须由FileStream对象执行.
其中创建FileStream对象最简单的构造函数如下:
FileStream file = new FileStream(fileName,FileMode.Member);//默认方式,可读可写
FileStream file = new FileStream(fileName, FileMode.Member, FileAccess.Member);
而FileAccess的成员:
成 员 | 说 明 |
Read | 打开文件,用于只读 |
Write | 打开文件,用于只写 |
ReadWrite | 打开文件,用于读写 |
对文件进行不是FileAccess枚举成员指定的操作会导致抛出异常。此属性的作用是,基于用户的身份验证级别改变用户对文件的访问权限。
在FileStream构造函数不使用FileAccess枚举参数的版本中,使用默认值FileAccess. ReadWrite。
FileMode枚举成员,使用每个值会发生什么,取决于指定的文件名是否表示已有的文件。
成 员 | 文 件 存 在 | 文件不存在 |
Append | 打开文件,流指向文件的末尾,只能与枚举FileAccess.Write联合使用 | 创建一个新文件。只能与枚举FileAccess.Write联合使用 |
Create | 删除该文件,然后创建新文件 | 创建新文件 |
CreateNew | 抛出异常 | 创建新文件 |
Open | 打开现有的文件,流指向文件的开头 | 抛出异常 |
OpenOrCreate | 打开文件,流指向文件的开头 | 创建新文件 |
Truncate | 打开现有文件,清除其内容。流指向文件的开头,保留文件的初始创建日期 | 抛出异常 |
FileStream类操作的是字节和字节数组,而Stream类操作的是字符数据
StreamWriter允许将字符和字符串写入文件,它处理底层的转换,向FileStream对象写入数据。StreamReader也类似。
实例:
using System;
using System.Data;
using System.IO;
using System.Text;
/// Summary description for FileReadAndWrite
public class FileReadAndWrite
{
public FileReadAndWrite()
{
// TODO: Add constructor logic here
}
/// 用FileStream写文件
public void FileStreamWriteFile(string str)
{
byte[] byData;
char[] charData;
try
{
FileStream nFile = new FileStream("love.txt", FileMode.Create);
//获得字符数组
charData = str.ToCharArray();
//初始化字节数组
byData = new byte[charData.Length];
//将字符数组转换为正确的字节格式
Encoder enc = Encoding.UTF8.GetEncoder();
enc.GetBytes(charData, 0, charData.Length,byData,0,true);
nFile.Seek(0, SeekOrigin.Begin);
nFile.Write(byData, 0, byData.Length);
}
catch (Exception ex)
{
throw ex;
}
}
/// FileStream读取文件
public string FileStreamReadFile(string filePath)
{
byte[] data = new byte[100];
char[] charData = new char[100];
try
{
FileStream file = new FileStream(filePath, FileMode.Open);
//文件指针指向0位置
file.Seek(0, SeekOrigin.Begin);
//读入两百个字节
file.Read(data, 0, 200);
//提取字节数组
Decoder dec = Encoding.UTF8.GetDecoder();
dec.GetChars(data, 0, data.Length, charData, 0);
}
catch (Exception ex)
{
throw ex;
}
return Convert.ToString(charData);
}
/// StreamWriter写文件
public void StreamWriterWriteFile()
{
try
{
FileStream nFile = new FileStream("love.txt", FileMode.CreateNew);
StreamWriter writer = new StreamWriter(nFile);
writer.WriteLine("I love You!");
writer.WriteLine("Do you love me!");
writer.Close();
}
catch
{ }
}
/// StreamReader读取文件
public string StreamReaderReadFile()
{
string str="";
try
{
FileStream file = new FileStream("love.txt", FileMode.Open);
StreamReader sr = new StreamReader(file);
while (sr.ReadLine()!=null)
{
str += sr.ReadLine();
}
//或者str = sr.ReadToEnd();
sr.Close();
}
catch
{ }
return str;
}
}
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛