文件操作--文本文件
1.FileStream 类:
1.1构造
FileStream对象表示在磁盘或网络路径上指向文件的流。这个类提供了在文件中读写字节的方法; 可以随机文件访问(访问文件中间某点的数据)。其他Stream类可以读写字符数据,但不能随机访问文件;
FileStream aFile = new FileStream(filename, FileMode.Member); FileStream aFile = new FileStream(filename, FileMode.Member, FileAccess. Member); FileStream fs = new FileStream(fileFullName, System.IO.FileMode.Member, System.IO.FileAccess.ReadWrite,FileShare.Member)
FileMode枚举:
成 员 |
文 件 存 在 |
文件不存在 |
Append |
打开文件,流指向文件的末尾,只能与枚举FileAccess.Write联合使用 |
创建一个新文件。只能与枚举FileAccess.Write联合使用 |
Create |
删除该文件,然后创建新文件 |
创建新文件 |
CreateNew |
抛出异常 |
创建新文件 |
Open |
打开现有的文件,流指向文件的开头 |
抛出异常 |
OpenOrCreate |
打开文件,流指向文件的开头 |
创建新文件 |
Truncate |
打开现有文件,清除其内容。流指向文件的开头,保留文件的初始创建日期 |
抛出异常 |
FileAccess枚举:指定了对流的作用(写,读,读/写),如果对文件进行不是FileAccess指定的操作,就会抛异常。默认值FileAccess.ReadWrite.
成 员 |
说 明 |
Read |
打开文件,用于只读 |
Write |
打开文件,用于只写 |
ReadWrite |
打开文件,用于读写 |
File和FileInfo类都提供了OpenRead()和OpenWrite()方法,更易于创建FileStream对象。前者打开了只读访问的文件,后者只允许写入文件。这些都提供了快捷方式,因此不必以FileStream构造函数的参数形式提供前面所有的信息。例如,下面的代码行打开了用于只读访问的Data.txt文件:
FileStream aFile = File.OpenRead("Data.txt");
注意下面的代码执行同样的功能:
FileInfo aFileInfo = new FileInfo("Data.txt"); FileStream aFile = aFile.OpenRead();
FileShare枚举:控制其他FileStream 对象对同一文件的共享操作。枚举在对文件在操作过程中,文件同时被其他对象的访问权限权限。
成 员 |
说 明 |
Read |
文件正本一个进程操作,则其他流对象只能读文件 |
Write |
文件正本一个进程操作,则其他流对象可以写文件 |
ReadWrite |
文件正本一个进程操作,则其他流对象可以读、写文件 |
None |
独占访问,包括读写。 |
1.2.文件定位
FileStream类维护内部文件指针,该指针指向文件中进行下一次读写操作的位置。在大多数情况下,当打开文件时,它就指向文件的开始位置,但是此指针可以修改。这允许应用程序在文件的任何位置读写,随机访问文件,或直接跳到文件的特定位置上。当处理大型文件时,这非常省时,因为马上可以定位到正确的位置。
实现此功能的方法是Seek()方法,它有两个参数:第一个参数规定文件指针以字节为单位的移动距离。第二个参数规定开始计算的起始位置,用SeekOrigin枚举的一个值表示。Seek Origin枚举包含3个值:Begin、Current和End。
例如,下面的代码行将文件指针移动到文件的第8个字节,其起始位置就是文件的第1个字节:
aFile.Seek(8,SeekOrigin.Begin); |
下面的代码行将指针从当前位置开始向前移动2个字节。如果在上面的代码行之后执行下面的代码,文件指针就指向文件的第10个字节:
aFile.Seek(2,SeekOrigin.Current); |
注意读写文件时,文件指针也会改变。在读取了10个字节之后,文件指针就指向被读取的第10个字节之后的字节。
也可以规定负查找位置,这可以与SeekOrigin.End枚举值一起使用,查找靠近文件末端的位置。下面的代码会查找文件中倒数第5个字节:
aFile.Seek(–5, SeekOrigin.End); |
以这种方式访问的文件有时称为随机访问文件,因为应用程序可以访问文件中的任何位置。稍后介绍的Stream类可以连续地访问文件,不允许以这种方式操作文件指针。
1.3.读取数据
使用FileStream类读取数据不像使用本章后面介绍的StreamReader类读取数据那样容易。这是因为FileStream类只能处理原始字节(raw byte)。处理原始字节的功能使FileStream类可以用于任何数据文件,而不仅仅是文本文件。通过读取字节数据,FileStream对象可以用于读取图像和声音的文件。这种灵活性的代价是,不能使用FileStream类将数据直接读入字符串,而使用StreamReader类却可以这样处理。但是有几种转换类可以很容易地将字节数组转换为字符数组,或者进行相反的操作。
FileStream.Read()方法是从FileStream对象所指向的文件中访问数据的主要手段。这个方法从文件中读取数据,再把数据写入一个字节数组。它有三个参数:第一个参数是传输进来的字节数组,用以接受FileStream对象中的数据。第二个参数是字节数组中开始写入数据的位置。它通常是0,表示从数组开端向文件中写入数据。最后一个参数指定从文件中读出多少字节。
byte[] byData = new byte[200]; char[] charData = new Char[200]; try { FileStream aFile = new FileStream("http://www.cnblogs.com/Program.cs",FileMode.Open); aFile.Seek(135,SeekOrigin.Begin); aFile.Read(byData,0,200); } catch(IOException e) { Console.WriteLine("An IO exception has been thrown!"); Console.WriteLine(e.ToString()); Console.ReadKey(); return; } Decoder d = Encoding.UTF8.GetDecoder(); d.GetChars(byData, 0, byData.Length, charData, 0); Console.WriteLine(charData); Console.ReadKey();
文件IO涉及到的所有操作都可以抛出类型为IOException的异常。所有产品代码都必须包含错误处理,尤其是处理文件系统时更是如此。
从文件中获取了字节数组后,就需要将其转换为字符数组,以便在控制台显示它。为此,使用System.Text命名空间的Decoder类。此类用于将原始字节转换为更有用的项,比如字符:
Decoder d = Encoding.UTF8.GetDecoder(); d.GetChars(byData, 0, byData.Length, charData, 0); |
这些代码基于UTF8编码模式创建了Decoder对象。这就是Unicode编码模式。然后调用GetChars()方法,此方法提取字节数组,将它转换为字符数组。完成之后,就可以将字符数组输出到控制台。
1.4. 写入数据
byte[] byData; char[] charData; try { FileStream aFile = new FileStream("Temp.txt", FileMode.Create); charData = "My pink half of the drainpipe.".ToCharArray(); byData = new byte[charData.Length]; Encoder e = Encoding.UTF8.GetEncoder(); e.GetBytes(charData, 0, charData.Length, byData, 0, true); // Move file pointer to beginning of file. aFile.Seek(0, SeekOrigin.Begin); aFile.Write(byData, 0, byData.Length); } catch (IOException ex) { Console.WriteLine("An IO exception has been thrown!"); Console.WriteLine(ex.ToString()); Console.ReadKey(); return; }
此应用程序在自己的目录中打开文件,并在文件中写入了一个简单的字符串。在结构上这个示例非常类似于前面的示例,只是用Write()代替了Read(),用Encoder代替了Decoder。
这次,要基于UTF8编码方法来创建Encoder对象。也可以将Unicode用于解码。这里在写入流之前,需要将字符数据编码为正确的字节格式。在GetBytes()方法中可以完成这些工作,它可以将字符数组转换为字节数组,并将字符数组作为第一个参数(本例中的charData),将该数组中起始位置的下标作为第二个参数(0表示数组的开头)。第三个参数是要转换的字符数量(charData.Length,charData数组中的元素个数)。第四个参数是在其中置入数据的字节数组(byData),第五个参数是在字节数组中开始写入位置的下标(0表示byData数组的开头)。
最后一个参数决定在结束后Encoder对象是否应该更新其状态,即Encoder对象是否仍然保留它原来在字节数组中的内存位置。这有助于以后调用Encoder对象,但是当只进行单一调用时,这就没有什么意义。最后对Encoder的调用必须将此参数设置为true,以清空其内存,释放对象,用于垃圾回收。
之后,使用Write()方法向FileStream写入字节数组就非常简单:
aFile.Seek(0,SeekOrigin.Begin); aFile.Write(byData,0,byData.Length); |
与Read()方法一样,Write()方法也有三个参数:要写入的数组,开始写入的数组下标和要写入的字节数。
2.StreamReader 类:从流中读取字符
3.StreamWriter类:它是按照一种特定的编码从字节流中写入字符,
3.1构造:
public StreamWriter(Stream stream, Encoding encoding); // // 摘要: // 使用默认编码和缓冲区大小,为指定路径上的指定文件初始化 System.IO.StreamWriter 类的新实例。如果该文件存在,则可以将其覆盖或向其追加。如果该文件不存在,则此构造函数将创建一个新文件。 // // 参数: // path: // 要写入的完整文件路径。 // // append: // 确定是否将数据追加到文件。如果该文件存在,并且 append 为 false,则该文件被覆盖。如果该文件存在,并且 append 为 true,则数据被追加到该文件中。否则,将创建新文件。 // // 异常: // System.UnauthorizedAccessException: // 访问被拒绝。 // // System.ArgumentException: // path 为空。- 或 -path 包含系统设备的名称(com1、com2 等等)。 // // System.ArgumentNullException: // path 为 null。 // // System.IO.DirectoryNotFoundException: // 指定的路径无效,比如在未映射的驱动器上。 // // System.IO.IOException: // path 包含不正确或无效的文件名、目录名或卷标的语法。 // // System.IO.PathTooLongException: // 指定的路径、文件名或者两者都超出了系统定义的最大长度。例如,在基于 Windows 的平台上,路径必须小于 248 个字符,文件名必须小于 260 // 个字符。 // // System.Security.SecurityException: // 调用方没有所要求的权限。 [SecuritySafeCritical] public StreamWriter(string path, bool append); // // 摘要: // 用指定的编码及缓冲区大小,为指定的流初始化 System.IO.StreamWriter 类的新实例。 // // 参数: // stream: // 要写入的流。 // // encoding: // 要使用的字符编码。 // // bufferSize: // 设置缓冲区大小。 // // 异常: // System.ArgumentNullException: // stream 或 encoding 为 null。 // // System.ArgumentOutOfRangeException: // bufferSize 为负。 // // System.ArgumentException: // stream 不可写。 [SecuritySafeCritical] public StreamWriter(Stream stream, Encoding encoding, int bufferSize); // // 摘要: // 使用指定编码和默认缓冲区大小,为指定路径上的指定文件初始化 System.IO.StreamWriter 类的新实例。如果该文件存在,则可以将其覆盖或向其追加。如果该文件不存在,则此构造函数将创建一个新文件。 // // 参数: // path: // 要写入的完整文件路径。 // // append: // 确定是否将数据追加到文件。如果该文件存在,并且 append 为 false,则该文件被覆盖。如果该文件存在,并且 append 为 true,则数据被追加到该文件中。否则,将创建新文件。 // // encoding: // 要使用的字符编码。 // // 异常: // System.UnauthorizedAccessException: // 访问被拒绝。 // // System.ArgumentException: // path 为空。- 或 -path 包含系统设备的名称(com1、com2 等等)。 // // System.ArgumentNullException: // path 为 null。 // // System.IO.DirectoryNotFoundException: // 指定的路径无效,比如在未映射的驱动器上。 // // System.IO.IOException: // path 包含不正确或无效的文件名、目录名或卷标的语法。 // // System.IO.PathTooLongException: // 指定的路径、文件名或者两者都超出了系统定义的最大长度。例如,在基于 Windows 的平台上,路径必须小于 248 个字符,文件名必须小于 260 // 个字符。 // // System.Security.SecurityException: // 调用方没有所要求的权限。 [SecuritySafeCritical] public StreamWriter(string path, bool append, Encoding encoding); // // 摘要: // 使用指定编码和缓冲区大小,为指定路径上的指定文件初始化 System.IO.StreamWriter 类的新实例。如果该文件存在,则可以将其覆盖或向其追加。如果该文件不存在,则此构造函数将创建一个新文件。 // // 参数: // path: // 要写入的完整文件路径。 // // append: // 确定是否将数据追加到文件。如果该文件存在,并且 append 为 false,则该文件被覆盖。如果该文件存在,并且 append 为 true,则数据被追加到该文件中。否则,将创建新文件。 // // encoding: // 要使用的字符编码。 // // bufferSize: // 设置缓冲区大小。 // // 异常: // System.ArgumentException: // path 为空字符串 ("")。- 或 -path 包含系统设备的名称(com1、com2 等等)。 // // System.ArgumentNullException: // path 或 encoding 为 null。 // // System.ArgumentOutOfRangeException: // bufferSize 为负。 // // System.IO.IOException: // path 包含不正确或无效的文件名、目录名或卷标的语法。 // // System.Security.SecurityException: // 调用方没有所要求的权限。 // // System.UnauthorizedAccessException: // 访问被拒绝。 // // System.IO.DirectoryNotFoundException: // 指定的路径无效,比如在未映射的驱动器上。 // // System.IO.PathTooLongException: // 指定的路径、文件名或者两者都超出了系统定义的最大长度。例如,在基于 Windows 的平台上,路径必须小于 248 个字符,文件名必须小于 260 // 个字符。 [SecuritySafeCritical] public StreamWriter(string path, bool append, Encoding encoding, int bufferSize);
3.2 Write() 和WriteLine()
try { using (StreamWriter sw= new StreamWriter("TestFile.txt")) { string str1 = "abc"; string str2 = "def"; sw.WriteLine(str1); sw.Write(str2); } } catch (Exception e) { Console.WriteLine("The file could not be read:"); Console.WriteLine(e.Message); }
StreamWriter sw = new StreamWriter(fs, System.Text.Encoding.Default);
来自参考:https://www.cnblogs.com/Fskjb/archive/2010/03/12/1684753.html