System.IO 命名空间
文件流类 FileStream
文件读写例子
读写二进制文件
读写内存流
本章小结
本章重点介绍 Windows 应用程序在文件读写中涉及的 System.IO 命名空间和 File、FileInfo、
FileStream、BinaryReader、BinaryWriter、BufferedStream 等类,以及常用的方法、参数、属性、事 件、枚举等。
了解 System.IO 命名空间
掌握读写文本文件的方法
掌握向文件读写二进制数据的方法
掌握读写内存流的方法
3.1 System.IO 命名空间
了解 System.IO 类和引用方式
了解 File 类的常用方法
了解 FileInfo 类的常用方法和主要属性
学习实现文件的复制方法
学习获取文件基本信息的方法
3
文件处理技术第 章
了解文件夹类 Directory 的常用方法
开发简易文本编辑器
以字节形式向磁盘写入的数据通常称为字节流(比特流)。存储在磁盘上的字节集合称为文件。
在 Windows 应用程序中,经常会读取文件中的数据,也会把处理后的数据存放到文件中,这就需 要对外存上的文件进行输入/输出(I/O)处理。例如,一名财务人员将单位的工资报表进行保存,
应用程序就会将数据以.xls 文件的形式保存到硬盘上。而另一位在家休假的员工想浏览旅游期间拍 摄的照片,应用程序就会读取存放在硬盘上的.bmp 文件。第三位员工要保留与好友的聊天记录,
应用程序就会将会话文本以.txt 文件的形式保存到硬盘上,如图 3-1 所示。
图 3-1 文件应用举例
3.1.1 System.IO 类介绍
.NET 2.0 环境下的软件系统开发已经把对文件的读写操作从底层转移到对类库的使用中。类库 结构中有一个 System.IO 命名空间,里面包含允许读写文件和数据流的类型以及提供基本文件和目 录支持的类型。一些常用的类如表 3-1 所示。
表 3-1 System.IO 命名空间常用的类
类 说明
File 提供用于创建、复制、删除、移动和打开文件的静态方法,并协助创建 FileStream 对象 FileInfo 提供用于创建、复制、删除、移动和打开文件的实例方法,并且帮助创建 FileStream 对
象。无法继承此类
FileStream 公开以文件为主的 Stream,既支持同步读写操作,也支持异步读写操作 BinaryReader 用特定的编码将基元数据类型读作二进制值
另存为.xls 文件
另存为.bmp 文件
另存为.txt 文件
续表
类 说明
BinaryWriter 以二进制形式将基元类型写入流,并支持用特定的编码写入字符串 BufferedStream 给另一流上的读写操作添加一个缓冲层。无法继承此类
Directory 公开用于创建、移动和枚举目录和子目录的静态方法。无法继承此类
DirectoryInfo 公开用于创建、移动和枚举目录和子目录的实例方法。无法继承此类
Path 对包含文件或目录路径信息的 String 实例执行操作。这些操作是以跨平台的方式执行的 StreamReader 实现一个 TextReader,使其以一种特定的编码从字节流中读取字符
StreamWriter 实现一个 TextWriter,使其以一种特定的编码向字节流中写入字符 FileSysWatcher 侦听文件系统更改通知,并在目录或目录中的文件发生更改时引发事件
这些类的结构如图 3-2 所示。
图 3-2 System.IO 命名空间的类结构图 此外还有几个常作为参数的枚举,如表 3-2 所示。
表 3-2 System.IO 命名空间常用的枚举
枚举 说明
FileMode 指定操作系统打开文件的方式
FileShare 包含用于控制其他 FileStream 对象对同一文件可以具有的访问类型
的常数
FileAccess 定义用于控制对文件的读访问、写访问或读/写访问的常数
小知识:System.IO 命名空间的引用
第 1 章提到了 Using 语句的使用,这里仍然建议使用 Using 来引用 System.IO 命名空间。若在代码页的 头部引用了 System.IO 命名空间
using System.IO;
在代码中就可以随意使用其所包含的类及枚举了,如 File.Creat();否则,需要在代码处加上 System.IO 前缀,
例如 System.IO. File.Creat()。
通过 MSDN 查看 System.IO 命名空间
打开 MSDN,选中“索引”标签,在“查找”文本框内输入 System.IO,在列表框中选中“System.IO 命 名空间”,右侧主界面会显示类、枚举、委托、结构列表。单击 File 类,就会看到关于 File 类的介绍,以及 语法、备注、示例、继承层次结构、线程安全、平台、版本信息、公共方法、参见等内容。通过这些帮助文 档,尤其是示例,读者可以容易地掌握 File 类的使用。
3.1.2 File 类的常用方法
利用 MSDN 就可以掌握类 File 的使用方法,File 类提供用于创建、复制、删除、移动和打开 文件的静态方法,并协助创建 FileStream 对象。类 File 有几个常用方法,如表 3-3 所示。
表 3-3 类 File 的常用方法
方法 说明
Move 将指定文件移到新位置,并提供指定新文件名的选项
Delete 删除指定的文件。如果指定的文件不存在,则不引发异常
Copy 已重载。将现有文件复制到新文件
CreateText 创建或打开一个文件用于写入 UTF-8 编码的文本
OpenText 打开现有 UTF-8 编码文本文件以进行读取
Open 已重载。打开指定路径上的 FileStream
案例学习:了解 File 类的一些主要方法 下面的示例演示了 File 类的一些主要方法。
using System;
using System.IO;
class Test {
public static void Main() {
string path=@"c:\temp\MyTest.txt";
if (!File.Exists(path)) {
//创建文件以便写入内容
using (StreamWriter sw=File.CreateText(path)) {
sw.WriteLine("Hello");
sw.WriteLine("And");
sw.WriteLine("Welcome");
} }
//打开文件,从中读数据
using (StreamReader sr=File.OpenText(path)) {
string s="";
while ((s=sr.ReadLine()) != null) {
Console.WriteLine(s);
} } try {
string path2=path+"temp";
//确认将要复制成的文件是否已经有同名的文件存在 File.Delete(path2);
//复制文件
File.Copy(path, path2);
Console.WriteLine("{0} was copied to {1}.", path, path2);
//删除新生成的文件 File.Delete(path2);
Console.WriteLine("{0} was successfully deleted.", path2);
}
catch (Exception e) {
Console.WriteLine("The process failed: {0}", e.ToString());
} } }
3.1.3 FileInfo 类的常用方法
FileInfo 类提供创建、复制、删除、移动和打开文件的实例方法,并且帮助创建 FileStream 对 象。FileInfo 类无法继承。FileInfo 类有几个常用属性,如表 3-4 所示。
表 3-4 类 FileInfo 的常用属性
属性 说明
Attributes 获取或设置当前 FileSystemInfo对象的FileAttributes属性(从FileSystemInfo类继承)
CreationTime 获取或设置当前 FileSystemInfo 对象的创建时间(从 FileSystemInfo类继承)
Directory 获取父目录的实例
DirectoryName 获取表示目录的完整路径的字符串
Exists 已重写。获取指示文件是否存在的值
Extension 获取表示文件扩展名部分的字符串(从 FileSystemInfo类继承)
案例学习:了解 FileInfo 类的一些主要属性 下面的示例演示了 FileInfo 类的一些主要属性。
using System;
using System.IO;
class Test {
public static void Main() {
string fileName="C:\\autoexec.bat";
FileInfo fileInfo=new FileInfo(fileName);
if (!fileInfo.Exists) {
return;
}
Console.WriteLine("{0} has a directoryName of {1}",fileName, fileInfo.DirectoryName);
/* 下面是代码的处理结果, * 实际的结果因机器不同:
*
* C:\autoexec.bat has a directoryName of C:\
*/
} }
案例学习:实现文件的复制
本案例将解决同磁盘环境下文件复制的问题。如何编写将 C:\WinNT\Win.INI 文件复制到 C:\
下的代码呢?
(1)向一个 Form 窗体上拖曳 3 个 Button 控件,控件的 text 属性分别设置为“复制文本文件”、
“创建文本文件”、“删除文本文件”,如图 3-3 所示。
图 3-3 文件操作界面
(2)双击“复制文本文件”、“创建文本文件”、“删除文本文件”按钮,在 click 事件处理方法 中分别添加代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace FileOptionApplication {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
///<summary>
///复制文本文件 ///</summary>
private void button1_Click(object sender, EventArgs e) {
string somefile=@"C:\Documents and Settings\Administrator\My Documents\SQL Server2000 安装故障.txt";
string target=@"C:\2.txt";
if (!File.Exists(somefile)) {
MessageBox.Show("文件不存在!");
} else {
if (File.Exists(target)) {
File.Delete(target);
}
File.Copy(somefile, target);
MessageBox.Show("文件复制成功!");
} }
///<summary>
///创建文本文件 ///</summary>
private void button2_Click(object sender, EventArgs e) {
string target=@"C:\2.txt";
if (File.Exists(target)) {
File.Delete(target);
}
File.CreateText(target);
}
///<summary>
///删除文本文件 ///</summary>
private void button3_Click(object sender, EventArgs e) {
string target=@"C:\2.txt";
if (File.Exists(target)) {
File.Delete(target);
MessageBox.Show("文件删除成功!");
} } } } 问题讨论
刚才的实验是通过 File 类实现的,那么如何通过更换 FileInfo 类执行同样的复制动作呢?请将 button1_Click 的代码替换为下列代码试试:
private void button1_Click(object sender, EventArgs e) {
string path=@"C:\Windows\IE4 Error Log.txt";
string target=@"C:\1.txt";
FileInfo myfile=new FileInfo(path);
if (!myfile.Exists) {
MessageBox.Show("对不起,未发现路径文件!");
} else {
myfile.CopyTo(target);
MessageBox.Show("复制成功!");
} }
案例学习:获取文件基本信息
本案例将解决如何显示文件的基本信息问题。
(1)向一个 Form 窗体上拖曳 3 个 Lable 控件和一个 Button 控件,Button 控件的 text 属性设 置为“获取文件信息”,如图 3-4 所示。
图 3-4 获取文件信息界面
(2)双击“获取文件信息”按钮,在 click 事件处理方法中分别添加代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace FileOptionApplication {
public partial class Form2 : Form {
public Form2() {
InitializeComponent();
}
///<summary>
///获取文件信息单击事件 ///</summary>
private void button1_Click(object sender, EventArgs e) {
string somefile=@"C:\Documents and Settings\Administrator\My Documents\SQL Server2000 安装故障.txt";
FileInfo myfile=new FileInfo(somefile);
if (myfile.Exists) {
MessageBox.Show("文件已经存在");
label1.Text="文件创建时间:"+myfile.CreationTime.ToString();
label2.Text="文件夹:"+myfile.Directory.ToString();
label3.Text="文件夹名称:"+myfile.DirectoryName.ToString()+",
文件扩展名:"+myfile.Extension.ToString();
} else {
MessageBox.Show("文件并不存在");
} } } } 问题讨论
FileInfo 类和 File 类都可以实现上述操作,它们的方法也都非常相似,那么它们到底有什么区 别呢?
File 为静态类,可直接使用;FileInfo 需要实例化后才能使用 。
从性能上考虑,如果要多次操作文件,不管是否针对相同文件,则应使用 FileInfo。
每次通过 File 类调用某个方法时,都要占用一定的 CPU,而 FileInfo 类只在创建 FileInfo 对象时执行一次安全检查。
3.1.4 文件夹类 Directory 的常用方法
Directory 类公开用于创建、移动和枚举通过目录和子目录的静态方法。Directory 类无法继承 此类。Directory 类有几个常用的静态方法,如表 3-5 所示。
表 3-5 Directory 类的常用方法
方法 说明
Move 将文件或目录及其内容移到新位置
Delete 已重载。删除指定的目录
CreateDirectory 已重载。创建指定路径中的所有目录 GetCreationTime 获取目录的创建日期和时间
GetCurrentDirectory 获取应用程序的当前工作目录
GetFiles 已重载。返回指定目录中的文件的名称
案例学习:了解 Directory 类的一些主要方法 下面的示例演示了 Directory 类的一些主要方法。
using System;
using System.IO;
class Test {
public static void Main() {
try {
//获取当前目录的创建时间
DateTime dt=Directory.GetCreationTime(Environment.CurrentDirectory);
//给用户反馈信息
if (DateTime.Now.Subtract(dt).TotalDays > 364) {
Console.WriteLine("This directory is over a year old.");
}
else if (DateTime.Now.Subtract(dt).TotalDays > 30) {
Console.WriteLine("This directory is over a month old.");
}
else if (DateTime.Now.Subtract(dt).TotalDays <= 1) {
Console.WriteLine("This directory is less than a day old.");
} else {
Console.WriteLine("This directory was created on {0}", dt);
} }
catch (Exception e) {
Console.WriteLine("The process failed: {0}", e.ToString());
} } }
案例学习:获取文件的基本物理磁盘信息
本案例将引导学生掌握如何显示文件的基本物理磁盘信息。
(1)向一个 Form 窗体上拖曳五个 Button 控件,其 text 属性分别设置为“创建目录”、“删除 目录”、“移动目录”、“目录创建时间”、“返回指定目录文件”,如图 3-5 所示。
图 3-5 操作界面
(2)在 Form3 类里添加两个静态字段 directory_path、directory_otherpath,都为 String 类型,
分别代表工作目录路径和其他目录路径;双击“创建目录”、“删除目录”、“移动目录”、“目录创建 时间”、“返回指定目录文件”按钮,在 click 事件处理方法中分别添加代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace FileOptionApplication {
public partial class Form3 : Form {
public Form3() {
InitializeComponent();
}
private static string directory_path="c:\\qs250";
private static string directory_otherpath="c:\\qqqq";
///<summary>
///“创建目录”按钮鼠标单击事件
///</summary>
private void button1_Click(object sender, EventArgs e) {
try {
Directory.CreateDirectory(directory_path);
button2.Enabled=true;
button1.Enabled=false;
button3.Enabled=true;
button4.Enabled=true;
button5.Enabled=true;
MessageBox.Show("文件夹成功建立。", "警报");
}
catch (Exception mm) {
MessageBox.Show("磁盘操作错误,原因:"+Convert.ToString(mm), "警报");
} }
///<summary>
///“删除目录”按钮鼠标单击事件 ///</summary>
private void button2_Click(object sender, EventArgs e) {
try {
Directory.Delete(directory_path);
button2.Enabled=false;
button1.Enabled=true;
button3.Enabled=false;
button4.Enabled=false;
button5.Enabled=false;
MessageBox.Show("文件夹删除建立。", "警报");
}
catch (Exception mm) {
MessageBox.Show("磁盘操作错误,原因:"+Convert.ToString(mm), "警报");
} }
///<summary>
///“移动目录”按钮鼠标单击事件 ///</summary>
private void button3_Click(object sender, EventArgs e) {
try {
Directory.Move(directory_path, directory_otherpath);
MessageBox.Show("文件夹移动成功。", "警报");
//例如,如果尝试将 C:\mydir 移到 C:\public,并且 C:\public 已存在 //则此方法引发IOException。必须将“C:\\public\\mydir”指定为destDirName //参数,或者指定新目录名,例如“C:\newdir”
}
catch (Exception mm) {
MessageBox.Show("磁盘操作错误,原因:"+Convert.ToString(mm), "警报");
} }
///<summary>
///“目录创建时间”按钮鼠标单击事件 ///</summary>
private void button4_Click(object sender, EventArgs e) {
try {
MessageBox.Show(string.Format("{0:G}",Directory.GetCreationTime (directory_path)), "提示");
//获取时间格式方法参见 DateTimeFormatInfo }
catch (Exception mm) {
MessageBox.Show("磁盘操作错误,原因:"+Convert.ToString(mm), "警报");
} }
///<summary>
///“返回指定目录文件”按钮鼠标单击事件 ///</summary>
private void button5_Click(object sender, EventArgs e) {
try {
string[] fileEntries=Directory.GetFiles(directory_path);
if (fileEntries.Length != 0) {
foreach (string s in fileEntries) {
if (File.Exists(s)) {
MessageBox.Show("内有文件信息:"+s, "提示");
} } } else {
MessageBox.Show("空文件夹", "提示");
}
//获取时间格式方法参见 DateTimeFormatInfo }
catch (Exception mm) {
MessageBox.Show("磁盘操作错误,原因:"+Convert.ToString(mm), "警报");
} } } }
3.1.5 File 类的常用操作的静态方法练习
文本文件是我们接触频繁的一类文件,记事本程序经常操作的文件就是文本文件,很多应用程 序会保存一些记录到日志文件里,这种日志文件也可以是文本文件。通过本节的学习,读者可以掌 握对文本文件的简单读写。
上节在介绍 System.IO 命名空间时,重点介绍了 File 类,本节将继续讨论 File 类。File 类是一 个静态类,不能被继承。它不仅提供一系列方法,用来针对文件的通用操作,还提供了一系列的读 写文本文件的方法,如表 3-6 所示。
表 3-6 File 类的读写文本文件方法
方法 说明
CreateText(string FilePath) 创建或打开一个文件,用于写入 UTF-8 编码的文本 OpenText(string FilePath) 打开现有 UTF-8 编码文本文件以进行读取
Open(string FilePath, FileMode) 打开指定路径上的 FileStream,具有读/写访问权限 Create(string FilePath) 在指定路径中创建文件
OpenRead(string FilePath) 打开现有文件以进行读取
AppendText(string FilePath) 创建一个 StreamWriter,它将 UTF-8 编码文本追加到现有文件 小知识:UTF-8 编码
UTF-8 是“UNICODE 八位交换格式”的简称,UNICODE 是国际标准,也是 ISO 10646 的等价标准。在 UNICODE 编 码 的 文 件 中可 以 同 时对 几 乎所 有 地球 上 已知 的 文 字字 符 进 行书 写 和表 示 ,而 且 已经 是 UNIX/Linux 的默认编码标准。在中国大陆常用的 GB2312/GB18030/GBK 系列标准是中国的国家标准,但只 能对中文和多数西方文字进行编码。为了保证网站的通用性,UTF-8 编码是更好的选择。
案例学习:简易文本编辑器的开发案例
本实验是对文本文件操作的综合练习,读者将在实验中逐渐熟悉并掌握对文本文件的操作技能。
(1)向一个 Form 窗体上拖曳两个 GroupBox 控件,text 属性分别设置为“写入文本”、“命名 文本文件:”;向两个 GroupBox 控件里拖曳一个 RichTextBox 控件和一个 TextBox 控件;向第一个 GroupBox 控件中拖曳两个 Button 控件,属性分别设置为“保存编辑文件”、“打开文本文件”;向
第二个 GroupBox 控件中拖曳一个 Button 控件,text 属性设置为“创建文本文件”,如图 3-6 所示。
图 3-6 简易文本编辑器界面
(2)在案例中添加一个静态字段 directory_path,string 类型,代表工作目录路径;双击“保存 编辑文件”、“打开文本文件”、“创建文本文件”按钮,在 click 事件处理方法中分别添加代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace FileOptionApplication {
public partial class Form4 : Form {
public Form4() {
InitializeComponent();
}
private static string directory_path="c:\\";
///<summary>
///创建文本文件 ///</summary>
private void button1_Click(object sender, EventArgs e) {
try {
if (textBox1.Text.Length==0)
{
MessageBox.Show("文件名禁止为空!", "警报");
} else {
directory_path=directory_path+textBox1.Text.Trim()+".txt";
//File.CreateText(..)返回的是一个 StreamWriter StreamWriter sw=File.CreateText(directory_path);
button2.Enabled=true;
button3.Enabled=true;
button1.Enabled=false;
richTextBox1.Enabled=true;
MessageBox.Show("文件文件成功建立。", "消息");
sw.Close();
} }
catch (Exception mm) {
MessageBox.Show("磁盘操作错误,原因:"+Convert.ToString(mm), "警报");
} }
///<summary>
///打开文本文件 ///</summary>
private void button2_Click(object sender, EventArgs e) {
try {
OpenFileDialog open=new OpenFileDialog();//创建一个打开的对话框 open.Title="打开文本文件";
open.FileName="";
open.AddExtension=true;//设置是否自动在文件中添加扩展名 open.CheckFileExists=true;//检查文件是否存在
open.CheckPathExists=true;//验证路径有效性
open.Filter="文本文件(*.txt)|*.txt";//设置将打开文件的类型 open.ValidateNames=true;
//文件有效性验证 ValidateNames,验证用户输入是否是一个有效的Windows 文件名 if (open.ShowDialog()==DialogResult.OK)
{
StreamReader sr=new StreamReader(open.FileName, System.Text.Encoding.Default);
this.richTextBox1.Text=sr.ReadToEnd();
}
MessageBox.Show("文件打开成功。", "消息");
}
catch (Exception mm)
{
MessageBox.Show("磁盘操作错误,原因:"+Convert.ToString(mm), "警报");
} }
///<summary>
///保存编辑文件 ///</summary>
private void button3_Click(object sender, EventArgs e) {
try {
FileStream textfile=File.Open(directory_path, FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter sw=new StreamWriter(textfile, Encoding.
GetEncoding("GB2312"));
sw.Write(richTextBox1.Text.ToString());
MessageBox.Show("文件写成功。", "警报");
}
catch (Exception mm) {
MessageBox.Show("磁盘操作错误,原因:"+Convert.ToString(mm), "警报");
} } } }
3.2 文件流类 FileStream
了解 FileStream 文件流类的特点
掌握 FileStream 文件流类的创建方法
了解 FileMode、FileAccess 和 FileShare 方法的基本介绍及注意事项
用 File 类提供的方法在创建或打开文件时,总会产生一个 FileStream 对象。FileStream 类是一 个什么样的类?怎样通过它的对象完成对文件的操作呢?
1.FileStream 文件流类简介
FileStream 对象也称为文件流对象,它为文件的读写操作提供通道,而 File 对象相当于提供一 个文件句柄。在文件操作中,针对 FileStream 对象的操作必须首先实例化一个 FileStream 类对象后 才可以进行,这一点与 File 类的操作是不一样的。
FileStream 类在实例化后可以用于读写文件中的数据,而要构造 FileStream 实例,需要以下 4 条信息:
(1)要访问的文件。
(2)表示如何打开文件的模式。例如,创建一个新文件或打开一个现有的文件。如果打开一 个现有的文件,写入操作是覆盖文件原来的内容,还是添加到文件的末尾?
(3)表示访问文件的方式——只读、只写,还是读写?
(4)共享访问——表示是否独占访问文件。如果允许其他流同时访问文件,则这些流是只读、
只写,还是读写文件?
2.FileStream 文件流类的创建
创建 FileStream 对象的方法不是单一的,除了使用 File 对象的 Create()方法或 Open()方法外,
也可以采用 FileStream 对象的构造函数。创建文件流对象的基本方法如下:
(1)使用 File 对象的 Create 方法。
FileStream mikecatstream;
mikecatstream=File.Create("c:\\mikecat.txt");
//本段代码的含义:
//利用类 File 的Create()方法在 C 盘根目录下创建文件 mikecat.txt,并把文件流赋给mikecatstream
(2)使用 File 对象的 Open 方法。
FileStream mikecatstream;
mikecatstream=File.Open("c:\\mikecat.txt", FileMode.OpenOrCreate, FileAccess.
Write);
//本段代码的含义:
//利用类 File 的 Open()方法打开在 C 盘根目录下的文件 mikecat.txt,打开的模式为打开或创 //建,对文件的访问形式为只写,并把文件流赋给 mikecatstream
(3)使用类 FileStream 的构造函数。
FileStream mikecatstream;
mikecatstream=new FileStream("c:\\mikecat.txt", FileMode.OpenOrCreate, FileAccess.Write);
//本段代码的含义:
//利用类 FileStream 的构造函数打开在 C:根目录下的文件 mikecat.txt,打开的模式为打开或创 //建,对文件的访问形式为只写,并把文件流赋给 mikecatstream
FileStream 类的构造函数提供了 15 种重载函数,最常用的有 3 种,如表 3-7 所示。
表 3-7 类 FileStream 的 3 种常用的构造函数
名称 说明
FileStream(string FilePath, FileMode) 使用指定的路径和创建模式初始化 FileStream 类的新实例 FileStream(string FilePath, FileMode,
FileAccess)
使用指定的路径、创建模式和读/写权限初始化 FileStream 类的 新实例
FileStream(string FilePath, FileMode, FileAccess, FileShare)
使 用 指 定 的 路 径 、 创 建 模 式 、 读 / 写 权限 和共 享权 限创建 FileStream 类的新实例
在构造函数中使用的 FilePath、FileMode、FileAccess、FileShare 分别是指使用指定的路径、
创建模式、读/写权限和共享权限。其中 FilePath 为将封装的文件的相对路径或绝对路径。
下面介绍 FileMode、FileAccess 和 FileShare。它们 3 个都是 System.IO 命名空间中的枚举类型,
如表 3-8 所示。
表 3-8 枚举类型 FileMode、FileAccess 和 FileShare
名称 取值 说明
FileMode Append 、 Create 、 CreateNew 、 Open 、
OpenOrCreate 和 Truncate 指定操作系统打开文件的方式
FileAccess Read、ReadWrite 和 Write 定义用于控制对文件的读访问、写访问或 读/写访问的常数
FileShare Inheritable、None、Read、ReadWrite 和 Write 包含用于控制其他 FileStream 对象对同 一文件可以具有的访问类型的常数 小实验 1
FileStream fstream=new FileStream("Test.cs", FileMode.OpenOrCreate, FileAccess.
ReadWrite, FileShare.None);
//本段代码的含义:
//利用 FileStream 类的构造函数打开当前目录下的文件 Test.cs,打开的模式为打开或创建,对文 //件的访问形式为读写,共享模式为拒绝共享,并把文件流赋给 fstream
小实验 2
FileStream s2=new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.Read);
//本段代码的含义:
//利用 FileStream 类的构造函数打开当前目录下的文件名为字符串 name 的文件,打开的模式为打 //开,对文件的访问形式为只读,共享模式为读共享,并把文件流赋给 s2
关于 FileMode、FileAccess 和 FileShare 这 3 个枚举类型值的含义,请参照表 3-9 至表 3-11 所示。
表 3-9 枚举类型 FileMode 枚举值的含义
成员名称 说明
Append 打开现有文件并查找到文件尾或创建新文件。FileMode.Append 只能同 FileAccess.Write 一起使用。任何读尝试都将失败并引发 ArgumentException
Create 指 定 操 作 系 统 应 创 建 新 文 件 。 如 果 文 件 已 存 在 , 则 将 被 改 写 。 此 操 作 要 求 FileIOPermissionAccess.Write。System.IO.FileMode.Create 等效于这样的请求:如果文件 不存在,则使用 CreateNew;否则使用 Truncate
CreateNew 指定操作系统应创建新文件。此操作需要 FileIOPermissionAccess.Write。如果文件已存在,
则将引发IOException
Open 指定操作系统应打开现有文件。打开文件的能力取决于 FileAccess 所指定的值。如果该文 件不存在,则引发 System.IO.FileNotFoundException
OpenOrCreate 指定操作系统应打开文件(如果文件存在);否则应创建新文件。如果用 FileAccess.Read 打开文件,则需要 FileIOPermissionAccess.Read。如果文件访问为 FileAccess.Write 或 FileAccess.ReadWrite , 则 需 要 FileIOPermissionAccess.Write 。 如 果 文 件 访 问 为 FileAccess.Append,则需要 FileIOPermissionAccess.Append
Truncate 指定操作系统应打开现有文件。文件一旦打开,就将被截断为零字节大小。此操作需要
FileIOPermissionAccess.Write。试图从使用 Truncate 打开的文件中进行读取将导致异常
表 3-10 枚举类型 FileAccess 枚举值的含义
成员名称 说明
Read 对文件的读访问。可从文件中读取数据。同 Write 组合即构成读写访问权 ReadWrite 对文件的读访问和写访问。可从文件读取数据和将数据写入文件
Write 文件的写访问。可将数据写入文件。同 Read 组合即构成读/写访问权 表 3-11 枚举类型 FileShare 枚举值的含义
成员名称 说明
Delete 允许随后删除文件
Inheritable 使文件句柄可由子进程继承。Win32 不直接支持此功能
None 谢绝共享当前文件。文件关闭前,打开该文件的任何请求(由此进程或另一进程发出的
请求)都将失败
Read 允许随后打开文件读取。如果未指定此标志,则文件关闭前,任何打开该文件以进行读
取的请求(由此进程或另一进程发出的请求)都将失败。但是,即使指定了此标志,仍 可能需要附加权限才能够访问该文件
ReadWrite 允许随后打开文件读取或写入。如果未指定此标志,则文件关闭前,任何打开该文件以
进行读取或写入的请求(由此进程或另一进程发出)都将失败。但是,即使指定了此标 志,仍可能需要附加权限才能够访问该文件
Write 允许随后打开文件写入。如果未指定此标志,则文件关闭前,任何打开该文件以进行写
入的请求(由此进程或另一进过程发出的请求)都将失败。但是,即使指定了此标志,
仍可能需要附加权限才能够访问该文件
在打开文件产生文件流的时候,三种枚举类型的不同枚举值作为参数会产生不同的操作效果,
具体应用应根据实际需要选择。
注意
对于 FileMode,如果要求的模式与文件的现有状态不一致,就会抛出一个异常。如果文件不存在,Append、
Open 和 Truncate 会抛出一个异常,如果文件存在,CreateNew 会抛出一个异常。Create 和 OpenOrCreate 可以 处理这两种情况,但 Create 会删除现有的文件,创建一个新的空文件。FileAccess 和 FileShare 枚举是按位标 志,所以这些值可以与 C#的按位 OR 运算符|合并使用。
3.3 文件的读写
学习通过文件流 FileStream 打开文本文件、写入文本文件、设置文件属性、实施对文件的 目录操作管理的基本方法
学习文件对话框的基本操作方法
学习通过文件流 FileStream 获取用户选择文件夹及文件的信息。
学习通过文件流 FileStream 建立一个新的文本文件,重新写文本信息流,以及如何在 C#
中定义文件和文件夹
学习文件流的资源释放意义以及释放资源的基本顺序
学习如何针对文本文件进行复杂的编辑、综合查询、删除、插入等操作
掌握对文件读写的程序的编写方法
案例学习:文件流 FileStream 综合案例(一)
本次实验目标是通过一个如图 3-7 所示的窗体,在单击相应按钮控件时,可以完成对文件的读 写操作、磁盘操作以及对目录的管理操作,使读者快速掌握操作文件、目录的技术方法及 FileStream 类的应用。
图 3-7 文件操作案例 1 界面图
(1)图 3-7 所示,从工具箱中拖曳五个 GroupBox 控件到 Form 窗体上,text 属性分别设置为
“文件管理”、“读写文件操作”、“文件磁盘操作”、“设置文件属性”、“目录管理”。向第一个 GroupBox 控件拖曳一个 RichTextBox 控件,再向第一个 GroupBox 控件拖曳一个 Button 控件,text 属性设置为“关闭”;向第二个 GroupBox 控件拖曳一个 ComboBox 控件,text 属性设置为“写入 类型选择:”,Items 属性中添加“创建空文本文件”、“添加入文本文件”、“新写入文本文件”;再向 第二个 GroupBox 控件拖曳两个 Button 控件,text 属性分别设置为“写入文件”、“读出文件”;向 第三个 GroupBox 控件拖曳一个 ComboBox 控件,text 属性设置为“文件磁盘操作选择:”,Items 属性中添加“文件创建”、“文件删除”、“文件复制”、“文件移动”;再向第三个 GroupBox 控件拖 曳一个 Button 控件,text 属性设置为“文件磁盘操作”;向第四个 GroupBox 控件拖曳两个 CheckBox 控件,text 属性分别设置为“只读”、“隐藏”;再向第四个 GroupBox 控件拖曳一个 Button 控件,text 属性设置为“属性确认”;向第五个 GroupBox 控件拖曳一个 ComboBox 控件,text 属性设置为“文 件目录操作选择:”,Items 属性中添加“创建文件夹”、“文件夹删除”、“文件夹移动”、“获取子文 件信息”;再向第五个 GroupBox 控件拖曳一个 Button 控件,text 属性设置为“文件目录操作”。
(2)双击所有 Button 控件,进入.cs 文件编辑状态准备进行开发,代码如下:
//=========================第一部分:主界面功能设计=============================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace FileOptionApplication {
public partial class Form6 : Form {
public Form6() {
InitializeComponent();
}
///<summary>
///读写文件操作 ///</summary>
private void button3_Click(object sender, EventArgs e) {
int p=comboBox1.SelectedIndex;
if (p==-1) {
MessageBox.Show("请您选择文件写入方式", "警告信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
} else {
string filecontent=richTextBox1.Text.Trim();
MyFileOption myoption=new MyFileOption();
string filepath=@"c:\1.txt";
bool i=myoption.WriteTextFile(filepath, filecontent, Convert.ToInt16 (comboBox1.SelectedIndex));
if (i==true) {
MessageBox.Show("保存成功", "保存信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
} else {
MessageBox.Show("写入文件时出错", "错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
} } }
///<summary>
///文件磁盘操作 ///</summary>
private void button4_Click(object sender, EventArgs e) {
Int16 p=Convert.ToInt16(comboBox2.SelectedIndex);
if (p==-1) {
MessageBox.Show("请您选择磁盘文件操作方式", "警告信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
} else {
string sourcepath="c:\\1.txt";
string targetpath="c:\\2.txt";
MyFileOption myoption=new MyFileOption();
bool i=myoption.DiskFileOption(sourcepath, targetpath, p);
if (i==true) {
MessageBox.Show("磁盘文件操作成功", "保存信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
} else {
MessageBox.Show("磁盘文件操作时出错", "错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
} } }
private void button1_Click(object sender, EventArgs e) {
richTextBox1.Text=null;
richTextBox1.Focus();
}
///<summary>
///读出文本文件内容 ///</summary>
private void button2_Click(object sender, EventArgs e) {
MyFileOption myoption=new MyFileOption();
string filepath=@"c:\1.txt";
Int16 i=0;
string filecontent="";
myoption.ReadTextFile(filepath, out i, out filecontent);
if (i==0) {
MessageBox.Show(filecontent, "错误信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
richTextBox1.Text=filecontent;
}
else if (i==1) {
richTextBox1.Text=filecontent;
MessageBox.Show("读取文件成功", "成功", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
else if (i==2) {
richTextBox1.Text=filecontent;
MessageBox.Show(filecontent, "错误信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
} }
///<summary>
///文件基本属性设置 ///</summary>
private void button5_Click(object sender, EventArgs e) {
string filepath=@"c:\1.txt";
if (checkBox1.Checked && checkBox2.Checked) {
File.SetAttributes(filepath, FileAttributes.ReadOnly | FileAttributes.Hidden);
MessageBox.Show("文件已经改为只读且隐藏", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
} else {
if (!checkBox1.Checked && !checkBox2.Checked) {
File.SetAttributes(filepath, FileAttributes.Archive);
MessageBox.Show("文件已经改为正常", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
} else {
if (checkBox2.Checked) {
File.SetAttributes(filepath, FileAttributes.ReadOnly);
MessageBox.Show("文件已经改为只读", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
if (checkBox1.Checked) {
File.SetAttributes(filepath, FileAttributes.Hidden);
MessageBox.Show("文件已经改为隐藏", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
} } } }
///<summary>
///文件夹操作 ///</summary>
private void button6_Click(object sender, EventArgs e) {
Int16 p=Convert.ToInt16(comboBox3.SelectedIndex);
if (p==-1) {
MessageBox.Show("请您选择文件夹操作方式", "警告信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
} else {
string sourcepath=@"c:\1";
string targetpath=@"c:\2";
MyFileOption myoption=new MyFileOption();
string[] filesname=null;
bool i=myoption.DirectoryOption(sourcepath, targetpath, p, out filesname);
if (i==true) {
MessageBox.Show("磁盘文件夹操作成功", "保存信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
if (filesname != null) {
foreach (string somestring in filesname) {
richTextBox1.Text+= somestring+"\r\n";
} } } else {
MessageBox.Show("磁盘文件夹操作时出错", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
} } } } }
(3)向项目中添加名为 FileOption.cs 的类文件,并准备填写关于文件操作的各种方法,如图 3-8 所示。
图 3-8 建立 FileOption.cs
(4)向 FileOption.cs 文件中添加代码如下:
//==============================第二部分:类设计============================
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace FileOptionApplication {
class MyFileOption {
///<summary>
/*******************************************************
**方法 名:WriteTextFile **输入参数:filepath:文件路径;
** filecontent:写入文件的内容;
** WriteMethord:写入方法(0:打开并创建文件;1:添加文本;2:新建文本)
**输出参数:逻辑类型参数 **返 回 值:bool **创 建 人:钱哨 **创建日期:09-7-9
**描 述:打开存放在某目录下的名称为filepath 文件,并在该文件中写入filecontent。
*******************************************************/
public bool WriteTextFile(string filepath, string filecontent, Int16 WriteMethord) {
bool i=true;
try {
if (WriteMethord==0) {
FileStream textfile=File.Open(filepath, FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter sw=new StreamWriter(textfile, Encoding.Default);
sw.Write(filecontent);
i=true;
sw.Close();
textfile.Close();
}
else if (WriteMethord==1) {
FileStream textfile=File.Open(filepath, FileMode.Append, FileAccess.Write);
StreamWriter sw=new StreamWriter(textfile, Encoding.Default);
sw.Write(filecontent);
i=true;
sw.Close();
textfile.Close();
}
else if (WriteMethord==2) {
FileStream textfile=File.Open(filepath, FileMode.Create, FileAccess.Write);
StreamWriter sw=new StreamWriter(textfile, Encoding.Default);
sw.Write(filecontent);
i=true;
sw.Close();
textfile.Close();
}
return i;
} catch {
i=false;
return i;
} }
///<summary>
/*******************************************************
**方 法 名:DiskFileOption
**输入参数: SourcePath:源文件路径;
** TargetPath:目的文件路径;
** OptionMethord:操作类别;0:文件创建;1:文件删除;2:文件复制;
3:文件移动 **输出参数:逻辑类型参数 **返 回 值:bool **创 建 人:钱哨
**创建日期:09-7-9
**描 述:对磁盘文件进行基本操作。
*******************************************************/
public bool DiskFileOption(string SourcePath, string TargetPath, Int16 OptionMethord)
{
bool i=true;
try {
if (OptionMethord==0) {
//文件创建
FileStream textfile=File.Create(SourcePath);
textfile.Close();
}
else if (OptionMethord==1) {
//文件删除
File.Delete(SourcePath);
}
else if (OptionMethord==2) {
//文件复制
File.Copy(SourcePath, TargetPath, true);
}
else if (OptionMethord==3) {
//文件移动
File.Move(SourcePath,TargetPath);
}
return i;
} catch {
i=false;
return i;
} }
///<summary>
/*******************************************************
**方 法 名:ReadTextFile **输入参数:filepath:文件路径;
**输出参数:i:读取类型(1:正常;2:文件读取错误;3:文件或路径无效);
** filecontent:返回内容 **返 回 值:逻辑类型参数
**创 建 人:钱哨
**创建日期:09-7-9
**描 述:读取存放在某目录下的名称为 filepath 的文件的内容。
*******************************************************/
public void ReadTextFile(string filepath, out Int16 i, out string filecontent) {
if (File.Exists(filepath)) {
try {
StreamReader textreader=new StreamReader(filepath, System.Text.
Encoding.Default);
filecontent=textreader.ReadToEnd();
textreader.Close();
i=1;
} catch {
i=2;
filecontent="文件读取错误!";
} } else {
i=0;
filecontent="文件或路径无效!";
} }
///<summary>
/*******************************************************
**方 法 名:DirectoryOption **输入参数:filepath:文件路径;
**输出参数:i:读取类型 (0:创建文件夹;1:文件夹删除;2:文件夹移动;3:获取文 件夹下面所有的子文件信息)
filecontent:返回内容 **返 回 值:逻辑类型参数 **创 建 人:钱哨
**创建日期:09-7-9
**描 述:读取存放在某目录下的名称为 filepath 的文件的内容。
*******************************************************/
///<summary>
public bool DirectoryOption(string Directorypath, string
TargetDirectorypath, Int16 OptionMethord, out string[] filesname) {
bool k=true;
filesname=null;
if (Directory.Exists(Directorypath))
{ try {
if (OptionMethord==0) {
//创建文件夹
Directory.CreateDirectory(Directorypath);
}
else if (OptionMethord==1) {
//文件夹删除
Directory.Delete(Directorypath, true);
}
else if (OptionMethord==2) {
//文件夹移动
Directory.Move(Directorypath, TargetDirectorypath);
}
else if (OptionMethord==3) {
//获取文件夹下面所有的子文件信息
filesname=Directory.GetFiles(Directorypath);
} } catch {
k=false;
} } else {
Directory.CreateDirectory(Directorypath);
k=true;
}
return k;
} } }
案例学习:文件流 FileStream 综合案例(二)
通过本案例,读者应用掌握以下内容:
如何通过用户选择文件夹获取文件夹信息
如何通过用户选择文件获取文件信息
如何通过文件流建立一个新的文本文件
如何打开文本文件后重新写文本信息流