C#开发Winform实现文件操作案例

目录
  • 一、文件对话框
    • (1)OpenFileDialog对话框
    • (2)SaveFileDialog对话框
    • (3)FolderBroswerDialog对话框
  • 二、文件及文件夹操作
    • (1)文件常用操作
    • (2)文件夹常用操作
    • (3)文件夹的复制和移动
      • 文件和流的概念:
      • 读写文本文件最常用的类有:
      • 读写文件操作的基本步骤为:
      • 文件流对象:
      • 文件读写器常用方法:
  • 三、读写文本文件
  • 四、序列化与反序列化
    • (1)序列化单个对象
    • (2)序列化集合

一、文件对话框

C#中共有三种文件对话框,分别用于不同的功能:

  • (1)用于打开文件的对话框OpenFileDialog。
  • (2)用于保存文件的对话框SaveFileDialog。
  • (3)打开文件夹的对话框FolderBroswerDialog。

示例:如下图,点击三个按钮分别弹出三种对话框,进行相应操作之后,将路径在文本框中显示:

(1)OpenFileDialog对话框

修改OpenFileDialog对话框的Name属性为ofDlg。在“打开”按钮添加ofDlg.ShowDialog(); 界面如下:

通过ShowDialog()的返回值,判断点击的是“打开”还是“取消”。在“打开”按钮点击事件中编写如下代码:

private void btnOpen_Click(object sender, EventArgs e)
{
    //判断是否点击的“打开”按钮
    if (ofDlg.ShowDialog() == DialogResult.OK)
    {
        txtPath.Text = ofDlg.FileName;
	}
}

OpenFileDialog常用属性表:

属性名 功能说明
InitialDirectory 对话框的初始目录
Filter 文件筛选器,按"显示名称|类型"格式编写 例如,"文本文件(.txt)|.txt|所有文件(.)||."
FilterIndex 在对话框中选择的文件筛选器的索引,如果选第一项就设为1
FileName 第一个在对话框中显示的文件或最后一个选取的文件
Title 将显示在对话框标题栏中的字符
CheckFileExists 在用户指定不存在的文件时是否显示警告
CheckPathExists 在对话框返回之前,检查指定路径是否存在

(2)SaveFileDialog对话框

保存文件对话框常用于软件中的“另存为”功能。其常用属性、方法及使用方式与打开文件对话框相同。

设置保存文件对话框的Filter属性为“文本文件|*.txt”。在“保存”按钮的点击事件中编写如下代码:

private void btnSave_Click(object sender, EventArgs e)
{
    if (sfDlg.ShowDialog() == DialogResult.OK)
    {
        txtPath.Text = sfDlg.FileName;
    }
}

(3)FolderBroswerDialog对话框

浏览文件夹对话框常用于浏览文件夹,选择文件夹路径。

在“浏览”按钮的点击事件中编写如下代码:

private void btnBrowse_Click(object sender, EventArgs e)
{
    if (fbDlg.ShowDialog() == DialogResult.OK)
    {
        txtPath.Text = fbDlg.SelectedPath;
    }
}

FolderBroswerDialog常用属性:

属性名 能说明功
Description 显示在对话框的树视图上方的字符串,用来指定显示给用户的指导信息
RootFolder 设置根文件夹位置
SelectedPath 对话框中最先选择的文件夹或用户最后选择的文件夹完整路径
ShowNewFold 对话框中是否包括“新建文件夹”按钮

二、文件及文件夹操作

文件及文件夹管理是操作系统的重要组成部分,主要包括创建、移动、复制和删除等操作。

Directory类和DirectoryInfo类用于对磁盘和文件夹的操作管理。

File类和FileInfo类用于对文件进行常用操作管理。

(1)文件常用操作

在C#中如果对文件进行创建、复制和删除等少量操作一般使用File类。

File类是静态类,其中所有方法都是静态的,通过类名直接调用,不需要实例化。

示例,如下图,进行文件的基本操作:

点击"选择文件"按钮选择某个文件,并将文件路径在文本框显示。

点击"选择文件夹"按钮选择某个文件夹,并将文件夹路径在文本框显示。

点击"复制文件"按钮,实现将文件复制到文件夹中。

点击"移动文件"按钮,实现将文件移动到文件夹中。

点击"删除文件"按钮,实现将文件删除。

其中,"选择文件"按钮name=btOpenFile,"选择文件夹"按钮name=btOpenFolder,"复制文件"按钮name=btCopy,"移动文件"按钮name=btMove,"删除文件"按钮name=btDelete。

存放文件名的文本框name=txtFile,存放文件夹名的文本框name=txtFolder。

文件对话框name=openFileDialog1,文件夹对话框name=folderBrowserDialog1。

File类实现代码如下:

//选择文件按钮
private void btOpenFile_Click(object sender, EventArgs e)
{
    if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
    {
        //FileName包含路径,SafeFileName不包含路径
        this.txtFile.Text = this.openFileDialog1.FileName;
    }
}
//选择文件夹按钮
private void btOpenFolder_Click(object sender, EventArgs e)
{
    if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
    {
        this.txtFolder.Text = this.folderBrowserDialog1.SelectedPath;
    }
}
//复制文件按钮
private void btCopy_Click(object sender, EventArgs e)
{
    if (!File.Exists(this.txtFile.Text))
    {
        MessageBox.Show("文件不存在!");
        return;
    }
    if (!Directory.Exists(this.txtFolder.Text))
    {
        MessageBox.Show("文件夹不存在!");
        return;
    }
    string[] arrName = this.txtFile.Text.Split('\\');
    string name = arrName[arrName.Length - 1];
    //第三个参数true代表文件存在直接覆盖
    //如果希望不覆盖,此处添加代码判断文件已经存在给出提示
    File.Copy(this.txtFile.Text, this.txtFolder.Text + "\\" + name,true);
    MessageBox.Show("复制成功!");
}

//移动文件
private void btMove_Click(object sender, EventArgs e)
{
    if (!File.Exists(this.txtFile.Text))
    {
        MessageBox.Show("文件不存在!");
        return;
    }
    if (!Directory.Exists(this.txtFolder.Text))
    {
        MessageBox.Show("文件夹不存在!");
        return;
    }
    string[] arrName = this.txtFile.Text.Split('\\');
    string name = arrName[arrName.Length - 1];
    string newFileName = this.txtFolder.Text + "\\" + name;
    if (File.Exists(newFileName))
    {
        //方案一:提示用户有重名文件
        //MessageBox.Show("目标位置有重名文件!");
        //return;

        //方案二:直接将目标文件删除
        File.Delete(newFileName);
    }
    File.Move(this.txtFile.Text, newFileName);
    MessageBox.Show("移动成功!");
}

//删除文件
private void btDelete_Click(object sender, EventArgs e)
{
    if (!File.Exists(this.txtFile.Text))
    {
        MessageBox.Show("文件不存在!");
        return;
    }
    File.Delete(this.txtFile.Text);
    MessageBox.Show("删除成功!");
}

和FileInfo类相比,使用File类可以避免频繁创建和释放对象的系统开销,但如果需要多次重用某个文件对象,则使用FileInfo类。

下面使用FileInfo类实现相同功能,代码如下:

//选择文件按钮
private void btOpenFile_Click(object sender, EventArgs e)
{
    if (this.openFileDialog1.ShowDialog() == DialogResult.OK)
    {
        //FileName包含路径,SafeFileName不包含路径
        this.txtFile.Text = this.openFileDialog1.FileName;
    }
}
//选择文件夹按钮
private void btOpenFolder_Click(object sender, EventArgs e)
{
    if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
    {
        this.txtFolder.Text = this.folderBrowserDialog1.SelectedPath;
    }
}
//复制文件
private void btCopy_Click(object sender, EventArgs e)
{
    FileInfo fInfo = new FileInfo(this.txtFile.Text);
    if (fInfo.Exists == false)
    {
        MessageBox.Show("文件不存在!");
        return;
    }
    DirectoryInfo dInfo = new DirectoryInfo(this.txtFolder.Text);
    if (dInfo.Exists == false)
    {
        MessageBox.Show("文件夹不存在!");
        return;
    }
    string[] arrName = this.txtFile.Text.Split('\\');
    string name = arrName[arrName.Length - 1];
    //第二个参数true代表文件存在直接覆盖
    fInfo.CopyTo(this.txtFolder.Text + "\\" + name, true);
    MessageBox.Show("复制成功!");
}
//移动文件
private void btMove_Click(object sender, EventArgs e)
{
    FileInfo fInfo = new FileInfo(this.txtFile.Text);
    if (fInfo.Exists == false)
    {
        MessageBox.Show("文件不存在!");
        return;
    }
    DirectoryInfo dInfo = new DirectoryInfo(this.txtFolder.Text);
    if (dInfo.Exists == false)
    {
        MessageBox.Show("文件夹不存在!");
        return;
    }
    string[] arrName = this.txtFile.Text.Split('\\');
    string name = arrName[arrName.Length - 1];
    string newFileName = this.txtFolder.Text + "\\" + name;
    FileInfo deskFile = new FileInfo(newFileName);
    if (deskFile.Exists == true)
    {
        //方案一:提示用户有重名文件
        //MessageBox.Show("目标位置有重名文件!");
        //return;

        //方案二:直接将目标文件删除
        deskFile.Delete();
    }
    fInfo.MoveTo(newFileName);
    MessageBox.Show("移动成功!");
}
//删除文件
private void btDelete_Click(object sender, EventArgs e)
{
    FileInfo fInfo = new FileInfo(this.txtFile.Text);
    if (fInfo.Exists == false)
    {
        MessageBox.Show("文件不存在!");
        return;
    }
    fInfo.Delete();
    MessageBox.Show("删除成功!");
}

(2)文件夹常用操作

Directory类是静态类,其中所有方法都是静态的,通过类名直接调用。

示例,如下图,进行文件夹的基本操作:

点击"选择文件夹一"按钮,选择文件夹,并把文件夹路径显示在第一个文本框。

点击"选择文件夹二"按钮,选择文件夹,并把文件夹路径显示在第二个文本框。

点击"移动文件夹"按钮,将第一个文本框路径的文件夹移动到第二个文本框路径的文件夹下。

点击"删除文件夹"按钮,将第一个文本框路径的文件夹进行删除。

其中"选择文件夹一"按钮name=btOpen1,"选择文件夹二"按钮name=btOpen2,"移动文件夹"按钮name=btMove,"删除文件夹"按钮name=btDelete。

第一个文本框name=txtFolder1,第二个文本框name=txtFolder2。

文件对话框name=openFileDialog1,文件夹对话框name=folderBrowserDialog1。

Directory实现代码如下:

//选择文件夹一
private void btOpen1_Click(object sender, EventArgs e)
{
    if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
    {
        this.txtFolder1.Text = this.folderBrowserDialog1.SelectedPath;
    }
}
//选择文件夹二
private void btOpen2_Click(object sender, EventArgs e)
{
    if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
    {
        this.txtFolder2.Text = this.folderBrowserDialog1.SelectedPath;
    }
}
//移动文件夹
private void btMove_Click(object sender, EventArgs e)
{
    if (!Directory.Exists(this.txtFolder1.Text) || !Directory.Exists(this.txtFolder2.Text))
    {
        MessageBox.Show("文件夹不存在!");
        return;
    }
    //获取文件夹名称
    string[] arrFolderName = this.txtFolder1.Text.Split('\\');
    string folderName = arrFolderName[arrFolderName.Length - 1];
    string newFolderName = this.txtFolder2.Text + "\\" + folderName;
    //判断目标地址是否已经有该文件夹了
    if (Directory.Exists(newFolderName))
    {
        //方案一:给出提示
        //MessageBox.Show("在目标位置,该文件夹已经存在了");
        //return;

        //方案二:删除目标位置的文件夹
        Directory.Delete(newFolderName,true);
    }
    //此移动操作只能在同一个根盘符上操作
    Directory.Move(this.txtFolder1.Text, newFolderName);
    MessageBox.Show("移动文件夹成功!");
}

private void btDelete_Click(object sender, EventArgs e)
{
    if (!Directory.Exists(this.txtFolder1.Text))
    {
        MessageBox.Show("文件夹不存在!");
        return;
    }
    //第二个参数代表删除所有的子文件夹和文件
    Directory.Delete(this.txtFolder1.Text, true);
    MessageBox.Show("删除文件夹成功!");
}

同样上述功能,使用DirectoryInfo实现如下:

//选择文件夹一
private void btOpen1_Click(object sender, EventArgs e)
{
    if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
    {
        this.txtFolder1.Text = this.folderBrowserDialog1.SelectedPath;
    }
}
//选择文件夹二
private void btOpen2_Click(object sender, EventArgs e)
{
    if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
    {
        this.txtFolder2.Text = this.folderBrowserDialog1.SelectedPath;
    }
}
//移动文件夹
private void btMove_Click(object sender, EventArgs e)
{
    DirectoryInfo startInfo = new DirectoryInfo(this.txtFolder1.Text);
    DirectoryInfo endInfo = new DirectoryInfo(this.txtFolder2.Text);
    if (startInfo.Exists == false || endInfo.Exists == false)
    {
        MessageBox.Show("文件夹不存在");
        return;
    }
    string[] arrFolderName = this.txtFolder1.Text.Split('\\');
    string folderName = arrFolderName[arrFolderName.Length - 1];
    string newFolderName = this.txtFolder2.Text + "\\" + folderName;
    //判断目标地址是否已经有该文件夹了
    DirectoryInfo tmp = new DirectoryInfo(newFolderName);
    if (tmp.Exists == true)
    {
        //方案一:给出提示
        //MessageBox.Show("在目标位置,该文件夹已经存在了");
        //return;
        //方案二:删除目标位置的文件夹
        tmp.Delete(true);
    }
    //此移动操作只能在同一个根盘符上操作
    startInfo.MoveTo(newFolderName);
    MessageBox.Show("移动成功!");
}

private void btDelete_Click(object sender, EventArgs e)
{
    DirectoryInfo startInfo = new DirectoryInfo(this.txtFolder1.Text);
    if (startInfo.Exists == false)
    {
        MessageBox.Show("文件夹不存在");
        return;
    }
    //参数代表删除所有的子文件夹和文件
    startInfo.Delete(true);
    MessageBox.Show("删除文件夹成功!");
}

(3)文件夹的复制和移动

关于文件夹的移动,系统提供给我们的功能,只能在同一个根盘符上操作。

关于文件夹的复制,系统根本就没有提供相应的API。

所以关于文件夹的复制以及文件移动跨磁盘只能自己写,自己实现了,如图:

点击"选择文件夹一"按钮:可以选择一个文件夹,并且将文件夹的路径显示在第一个文本框。

点击"选择文件夹二"按钮:可以选择一个文件夹,并且将文件夹的路径显示在第二个文本框。

点击"复制文件夹"按钮:将第一个文件夹及文件夹内容复制到第二个文件夹中。

点击"移动文件夹"按钮:将第一个文件夹及文件夹内容移动到第二个文件夹中。

其中:"选择文件夹一"按钮name=btOpen1,"选择文件夹二"按钮name=btOpen2,"复制文件夹"按钮name=btCopy,"移动文件夹"按钮name=btMove。

第一个文本框name=txtFolder1,第二个文本框name=txtFolder2。

文件对话框name=openFileDialog1,文件夹对话框name=folderBrowserDialog1。

具体实现代码如下:

编写通用的递归方法,实现文件夹的复制:

//endFolderPath为处理之后的目标路径
//例如将"C:\abc"复制到"D:123\",endFolderPath需要传递处理之后的"D:123\abc"
private void CopyFolder(string startFolderPath, string endFolderPath)
{
    //在创建目标文件夹
    Directory.CreateDirectory(endFolderPath);
    DirectoryInfo startDir = new DirectoryInfo(startFolderPath);
    //循环复制文件夹下的所有文件
    foreach (FileInfo item in startDir.GetFiles())
    {
        File.Copy(item.FullName, endFolderPath + "\\" + item.Name);
    }
    //循环所有子文件夹形成递归调用
    foreach (DirectoryInfo item in startDir.GetDirectories())
    {
        string startPath = item.FullName;
        string newFolderName = endFolderPath + "\\" + item.Name;
        CopyFolder(startPath, newFolderName);
    }
}

各个按钮的代码如下:

private void btOpen1_Click(object sender, EventArgs e)
{
    if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
    {
    	this.txtFolder1.Text = this.folderBrowserDialog1.SelectedPath;
    }
}

private void btOpen2_Click(object sender, EventArgs e)
{
    if (this.folderBrowserDialog1.ShowDialog() == DialogResult.OK)
    {
    	this.txtFolder2.Text = this.folderBrowserDialog1.SelectedPath;
    }
}
//复制文件夹
private void btCopy_Click(object sender, EventArgs e)
{
    if (!Directory.Exists(this.txtFolder1.Text) || !Directory.Exists(this.txtFolder2.Text))
    {
        MessageBox.Show("文件夹不存在!");
        return;
    }
    string[] arrFolderName = this.txtFolder1.Text.Split('\\');
    string folderName = arrFolderName[arrFolderName.Length - 1];
    string newFolderName = this.txtFolder2.Text + "\\" + folderName;
    //判断目标地址是否已经有该文件夹了
    if (Directory.Exists(newFolderName))
    {
        //方案一:给出提示
        //MessageBox.Show("在目标位置,该文件夹已经存在了");
        //return;

        //方案二:删除目标位置的文件夹
        Directory.Delete(newFolderName, true);
    }
    CopyFolder(this.txtFolder1.Text, newFolderName);
    MessageBox.Show("复制成功!");
}

//移动文件夹
private void btMove_Click(object sender, EventArgs e)
{
    if (!Directory.Exists(this.txtFolder1.Text) || !Directory.Exists(this.txtFolder2.Text))
    {
        MessageBox.Show("文件夹不存在!");
        return;
    }
    string[] arrFolderName = this.txtFolder1.Text.Split('\\');
    string folderName = arrFolderName[arrFolderName.Length - 1];
    string newFolderName = this.txtFolder2.Text + "\\" + folderName;
    //判断目标地址是否已经有该文件夹了
    if (Directory.Exists(newFolderName))
    {
        //方案一:给出提示
        //MessageBox.Show("在目标位置,该文件夹已经存在了");
        //return;

        //方案二:删除目标位置的文件夹
        Directory.Delete(newFolderName, true);
    }
    CopyFolder(this.txtFolder1.Text, newFolderName);
    //复制完成后,删除原始位置的文件夹
    Directory.Delete(this.txtFolder1.Text, true);
    MessageBox.Show("移动成功!");
}

三、读写文本文件

文件和流的概念:

--文件是在各种媒质上永久存储的数据的有序集合。它是进行数据读写操作的基本对象。

--流是一种向存储器读取和写入字节的方式,也是进行数据读写操作的基本对象。

--流提供了连续的字节流存储空间,其实际存储位置可以不连续。

--C#中所有表示流的类都继承于抽象类Stream。

读写文本文件最常用的类有:

--FileStream(文件流)

--StreamReader(流读取器)

--StreamWriter(流写入器)

读写文件操作的基本步骤为:

  • 创建文件流
  • 创建读、写器
  • 执行读、写操作
  • 关闭读写器
  • 关闭文件流

文件流对象:

实例化文件流对象语法如下:

FileStream fs = new FileStream(FileName, FileMode,FileAccess);

其中FileMode的枚举值如下:

值名称 功能说明
CreateNew 创建新文件,如果文件已存在则引发异常
Create 创建新文件,如果文件已存在则覆盖
Open 打开文件,如果文件不存在则引发异常
OpenOrCreate 打开文件,如果文件不存在则创建新文件
Append 打开文件并查找到文件尾,如果文件不存在则创建新文件
Truncate 打开现在文件并清除其内容,如果文件不存在则引发异常

其中FileAccess的枚举值如下:

值名称 功能说明
Read 对文件进行只读访问
Write 对文件进行只写访问
ReadWrite 对文件进行读写访问

文件读写器常用方法:

StreamReader的常用方法:

值名称 功能说明
Read 读取输入流中的下一个(组)字符
ReadLine 读取当前流中的一行字符,并将数据作为字符串返回
ReadToEnd 读取从当前位置到末尾的所有字符,并将数据作为字符串返回
Close 关闭StreamReader对象和基础流,并释放与读取器关联的所有系统资源

StreamWriter的常用方法:

值名称 功能说明
Write 将数据写入流
WriteLine 将行结束符之前的数据写入流
Close 关闭StreamWriter对象和基础流

示例:如下图,编写一个文本文件读写器

--点击"打开文件"按钮,选择一个文本文件,并且将文本文件路径显示在上面单行文本框中,将文本文件的内容显示在下面的多行文本框中。

--多行文本框,可以进行修改其文本内容。

--点击"保存文件"按钮,将多行文本框的文本保存到打开的文本文件中。

其中"打开文件"按钮name=btOpen,"保存文件"按钮name=btSave,单行文本框name=txtFilePath,多行文本框name=txtContent。

实现代码如下:

private void btOpen_Click(object sender, EventArgs e)
{
    OpenFileDialog dialog = new OpenFileDialog();
    DialogResult result = dialog.ShowDialog();
    //点击打开按钮之后
    if (result == System.Windows.Forms.DialogResult.OK)
    {
        this.txtFilePath.Text = dialog.FileName;
    }
    else
    {
    	return;
    }
    //方案一:使用Filestream将文本一次性全部转换为字节数组,之后转换为string
    //FileStream fs = new FileStream(this.txtFilePath.Text, FileMode.Open, FileAccess.Read);
    ////fs.Seek(0, SeekOrigin.Begin); //定位流,从开始位置移动0个字节,也就是流的最开始位置
    //int len = (int)fs.Length; //获取文件的字节长度
    //byte[] arrByte = new byte[len]; //定义字节数组
    //fs.Read(arrByte, 0, arrByte.Length); //将文件流读入字节数组
    //this.txtContent.Text = Encoding.Default.GetString(arrByte,0,len);
    //fs.Close();

    //方案二:使用Filestream,逐字节读取文本,后将字节转换为string
    //FileStream fs = new FileStream(this.txtFilePath.Text, FileMode.Open, FileAccess.Read);
    //int len = (int)fs.Length; //获取文件的字节长度
    //byte[] arrByte = new byte[len]; //定义字节数组
    //int index = 0; //保存字节数组变化的下标
    //int code = fs.ReadByte(); //读取一个字节
    //while (code != -1) //读取内容等于-1即表示读取完毕
    //{
    //    //将读取内容转换成字节存入数组
    //    arrByte[index] = Convert.ToByte(code);
    //    code = fs.ReadByte();  //继续逐字节读取
    //    index++;
    //}
    //this.txtContent.Text = Encoding.Default.GetString(arrByte, 0, len);
    //fs.Close();

	//方案三:直接使用File的Read All Text 函数将文本文件内容全部读入text
	//File.ReadAllBytes可以读取成字节数组
	//this.txtContent.Text = File.ReadAllText(this.txtFilePath.Text, Encoding.Default);

    //方案四:使用StreamReader流读取器读取
    FileStream fs = new FileStream(this.txtFilePath.Text, FileMode.Open, FileAccess.Read);
    StreamReader sd = new StreamReader(fs, Encoding.Default);
    //这里可以逐行读入
    //string line = sd.ReadLine();
    //while (line != null)
    //{
    //    this.txtContent.Text = this.txtContent.Text + line + "\r\n";
    //    line = sd.ReadLine();
    //}
    //也可以全部读入
    this.txtContent.Text = sd.ReadToEnd();
    sd.Close();
    fs.Close();
}

private void btSave_Click(object sender, EventArgs e)
{
    //方案一:File类静态方法
    //File.WriteAllText(this.txtFileName.Text, this.txtContent.Text,Encoding.Default);
    //MessageBox.Show("保存成功!");

    //方案二:使用StreamWriter流写入器
    FileStream fs = new FileStream(this.txtFileName.Text, FileMode.Open, FileAccess.Write);
    StreamWriter sw = new StreamWriter(fs, Encoding.Default);
    sw.Write(this.txtContent.Text);
    sw.Close();
    fs.Close();
    MessageBox.Show("保存成功!");
}

四、序列化与反序列化

序列化就是将对象实例的状态存储到存储媒介的过程。

序列化和反序列化的实现步骤(二进制序列化):

  • (1)引入System.Runtime.Serialization.Formatters.Binary命名空间
  • (2)要序列化的对象需要标记Serializable特性
  • (3)其父类和属性中的引用类型也标记Serializable特性
  • (4)使用BinaryFormatter 对象的Serialize()方法和Deserialize()方法

(1)序列化单个对象

示例:如下图,实现单个对象的序列化与反序列化

--输入学生信息,点击"保存信息"按钮,将学生信息永久序列化保存到电脑上。

--关闭程序后,在启动程序,可以将本地序列化文件读取,将信息显示在界面的文本框中。

其中,学号,姓名,年龄文本框的name分别为txtNo,txtName,txtAge。

保存信息和读取信息按钮name分别为btSave和btRead。

具体实现代码如下:

定义一个学生类:

[Serializable]
class Student
{
    public string StuNo { get; set; } //学号
    public string StuName { get; set; } //姓名
    public int StuAge { get; set; } //年龄
}

其中[Serializable]关键字代表此类是可以被序列化的。

编写按钮响应事件代码:

private void btSave_Click(object sender, EventArgs e)
{
    Student stu = new Student();
    stu.StuNo = this.txtNo.Text;
    stu.StuName = this.txtName.Text;
    stu.StuAge = int.Parse(this.txtAge.Text);

    FileStream fs = new FileStream("stu.ini", FileMode.Create, FileAccess.ReadWrite);
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(fs, stu);  //序列化
    fs.Close();
    MessageBox.Show("保存成功!");
}

private void btRead_Click(object sender, EventArgs e)
{
    FileStream fs = new FileStream("stu.ini", FileMode.Open, FileAccess.ReadWrite);
    BinaryFormatter bf = new BinaryFormatter();
    Student stu = bf.Deserialize(fs) as Student;  //反序列化
    this.txtNo.Text = stu.StuNo;
    this.txtName.Text = stu.StuName;
    this.txtAge.Text = stu.StuAge.ToString();
    fs.Close();
}

(2)序列化集合

示例:如下图,实现集合的序列化

--打开窗体,自动从序列化文件中读取信息,并在listView列表上进行展示。

--输入学生信息,点击"添加信息"按钮,添加学生,并且序列化学生列表,刷新ListView列表数据。

其中展示列表的ListView控件的name=listView1。

学号,姓名,年龄文本框的name分别为txtNo,txtName,txtAge。

添加信息按钮name=btSave。

具体实现代码如下:

定义一个学生类:

[Serializable]
class Student
{
    public string StuNo { get; set; } //学号
    public string StuName { get; set; } //姓名
    public int StuAge { get; set; } //年龄
}

其中[Serializable]关键字代表此类是可以被序列化的。

编写按钮响应事件代码:

List<Student> list = new List<Student>();
private void BindData()
{
    if (!File.Exists("list.ini"))
        return;
    //读取序列化文件
    FileStream fs = new FileStream("list.ini", FileMode.Open, FileAccess.ReadWrite);
    BinaryFormatter bf = new BinaryFormatter();
    list = bf.Deserialize(fs) as List<Student>;  //反序列化
    fs.Close();
    //将list集合数据绑定到ListView控件
    this.listView1.Items.Clear();
    foreach (Student stu in list)
    {
        ListViewItem item = new ListViewItem(stu.StuNo);
        item.SubItems.Add(stu.StuName);
        item.SubItems.Add(stu.StuAge.ToString());
        this.listView1.Items.Add(item);
    }
}

private void Form2_Load(object sender, EventArgs e)
{
    BindData();
}

private void btSave_Click(object sender, EventArgs e)
{
    Student stu = new Student();
    stu.StuNo = this.txtNo.Text;
    stu.StuName = this.txtName.Text;
    stu.StuAge = int.Parse(this.txtAge.Text);
    list.Add(stu);
    FileStream fs = new FileStream("list.ini", FileMode.Create, FileAccess.ReadWrite);
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(fs, list);  //序列化
    fs.Close();
    MessageBox.Show("保存成功!");
    BindData();
}

到此这篇关于C#开发Winform实现文件操作案例的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#实现文件Move和Copy操作

    文件移动(Move)操作和文件的复制(Copy)是C#程式开发经常遇到的方法,根据传入的源文件地址和目标文件地址参数,实现对文件的操作.实现代码如下: Move操作代码 public static void MoveFolder(string sourcePath, string destPath) { if (Directory.Exists(sourcePath)) { if (!Directory.Exists(destPath)) { //目标目录不存在则创建 try { Directo

  • C#文件操作、读取文件、Debug/Trace类用法

    1.文件操作 这段代码在 System.Private.CoreLib 下,对 System.IO.File 中的代码进行精简,供 CLR 使用. 当使用文件时,要提前判断文件路径是否存在,日常项目中要使用到文件的地方应该不少,可以统一一个判断文件是否存在的方法: public static bool Exists(string? path) { try { // 可以将 string? 改成 string if (path == null) return false; if (path.Len

  • C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    本文实例讲述了C#实现的文件操作封装类.分享给大家供大家参考,具体如下: 最近发现群共享里面有个C# 文件操作封装类,其方法是调用Windows API 来操作的文件的删除.移动.复制.重命名操作.下载下来一试,发现果然不错,特在此记录,以防丢失! 文件操作类代码如下: using System; using System.Runtime.InteropServices; using System.IO; namespace LxFile { /// <summary> /// 文件操作代理,

  • c# 文件操作(移动,复制,重命名)

    文件移动 public static void MoveFolder(string sourcePath, string destPath) { if (Directory.Exists(sourcePath)) { if (!Directory.Exists(destPath)) { //目标目录不存在则创建 try { Directory.CreateDirectory(destPath); } catch (Exception ex) { throw new Exception("创建目标

  • C#文件目录操作方法汇总

    需要 using System.IO; 1) 相对路径转绝对路径 string fullfolder = HttpContext.Current.Server.MapPath(folder); 2) 文件移动(改名) File.Move(Server.MapPath("/a.txt"), Server.MapPath("/b.txt")); 3) 文件复制 File.Copy(Server.MapPath("/a.txt"), Server.Ma

  • C#文件操作类分享

    本文实例为大家分享了C#文件操作类的具体代码,供大家参考,具体内容如下 using System; using System.Collections.Generic; using System.Text; using System.Data; using System.Reflection; using System.Collections; using System.Data.Common; namespace DotNet.Utilities { //JSON转换类 public class

  • C#操作ini文件的帮助类

    一.定义Class using System; using System.Runtime.InteropServices; using System.Text; namespace IniDemo { public class IniFile { private string m_FileName; public string FileName { get { return this.m_FileName; } set { this.m_FileName = value; } } [DllImp

  • C# 文件操作函数 创建文件 判断存在

    文件创建: 复制代码 代码如下: File.Create(Application.StartupPath + "\\AlarmSet.txt");//创建该文件 System.IO.Path.GetFileName(filePath)       //返回带扩展名的文件名 System.IO.Path.GetFileNameWithoutExtension(filePath)     //返回不带扩展名的文件名 System.IO.Path.GetDirectoryName(fileP

  • C#开发Winform实现文件操作案例

    目录 一.文件对话框 (1)OpenFileDialog对话框 (2)SaveFileDialog对话框 (3)FolderBroswerDialog对话框 二.文件及文件夹操作 (1)文件常用操作 (2)文件夹常用操作 (3)文件夹的复制和移动 文件和流的概念: 读写文本文件最常用的类有: 读写文件操作的基本步骤为: 文件流对象: 文件读写器常用方法: 三.读写文本文件 四.序列化与反序列化 (1)序列化单个对象 (2)序列化集合 一.文件对话框 C#中共有三种文件对话框,分别用于不同的功能:

  • Python编程快速上手——PDF文件操作案例分析

    本文实例讲述了Python PDF文件操作.分享给大家供大家参考,具体如下: 题目如下: 利用第九章的os.walk()函数编写脚本,遍历文件夹中的所有pdf,用命令行提供的命令对这些PDF进行加密,用原来的文件名加上_encrypted.pdf后缀,保存每个加密的PDF.在删除原来的文件之前,尝试用程序读取并解密该文件,确保被正确加密 然后编写一个程序,找到文件夹中所有加密的PDF文件,利用提供的口令,创建pdf的解密拷贝,如果口令不对,程序应该打印一条消息, 并继续处理下一个pdf文件 思路

  • C#使用三层架构开发Winform的详细案例

    三层架构将整个业务应用划分为: (1)界面UI层 (2)业务逻辑层 (3)数据访问层 对于复杂的系统分层可以让结构更加清晰,模块更加独立,便于维护. 各层的任务: (1)数据访问层:负责数据库的操作. (2)业务逻辑层:实现功能模块的业务逻辑. (3)界面UI层:绘制界面,以及负责界面相关代码. (4)实体类:将数据库中的表转化为面向对象思想中的类. 一.案例需求 使用三层架构实现学生管理: (1)专业下拉框绑定专业表数据,网格控件绑定学生数据,并且点击"搜索"按钮可以多条件组合查询.

  • python开发之文件操作用法实例

    本文实例讲述了python开发之文件操作用法.分享给大家供大家参考,具体如下: 先来看看官方API:os-Miscellaneous operating system interfaces 下面是我做的demo: import re import os import time #图片文件路径 image_path = 'E:\\test\\20130627_140132Hongten.jpg' #文件夹路径 dir_path = 'E:\\test\\hongten' #文件路径 file_ab

  • Android开发之文件操作详解

    本文实例讲述了Android开发之文件操作.分享给大家供大家参考,具体如下: 目前,几乎所有的设备都会涉及到文件的操作,例如什么电脑,手机等设备.Android的文件操作和电脑是比较类似的,既可以存储在手机内置的存储器里也可以是sd卡.在这篇文章里主要介绍在手机内置存储器里的文件操作. 一. 开发流程 (1)界面的设计 (2)设计android的业务层 (3)单元测试 (4)设置android的控制器层 二. 开发步骤 (1)设计软件界面 <?xml version="1.0"

  • 案例讲解WEB 漏洞-文件操作之文件下载读取

    目录 原理 漏洞危害 利用方式 系统文件 window Linux 常见脚本敏感文件参考 任意文件读取 任意文件下载 Google search 漏洞利用代码 漏洞挖掘 漏洞验证 漏洞防范 案例 pikuchu靶场-文件下载测试 小米路由器-文件读取真实测试-漏洞 RoarCTF2019-文件读取真题复现 百度杯2017二月-Zone真题复现 原理 产生:任意语言代码下载函数 文件下载(一些网站由于业务需求,往往需要提供文件查看或文件下载功能,但若对用户查看或下载的文件不做限制,则恶意用户就能够

  • C#开发Winform控件之打开文件对话框OpenFileDialog类

    OpenFileDialog类提供了用户打开文件的功能,它有如下属性: 属性 InitialDirectory:设置对话框的初始目录. Filter: 要在对话框中显示的文件筛选器,例如,"文本文件(*.txt)|*.txt|所有文件(*.*)||*.*". FilterIndex: 在对话框中选择的文件筛选器的索引,如果选第一项就设为1. RestoreDirectory: 控制对话框在关闭之前是否恢复当前目录. FileName:第一个在对话框中显示的文件或最后一个选取的文件. T

  • Python文件操作实战案例之用户登录

    目录 一.前言 二.案例:用户登录 1.案例分析 2.程序设计 2.1 main() 2.2 c_flag() 2.3 init() 2.4 print_login_menu() 2.5 user_select() 2.6 root_login() 2.7 user_register() 2.8 user_login() 3.功能演示 总结 一.前言 在上一小节,我们介绍了文件的基本操作以及数据交换的格式,为了巩固我们上一节文件操作的知识. 在这里我们做一个最基本的案例:用户登录 二.案例:用户

  • Go语言文件读写操作案例详解

    目录 基本介绍 文件基本操作 读操作 写操作 写操作案例 查看文件或目录是否存在 拷贝文件 基本介绍 文件,对我们并不陌生,文件是数据源(保存数据的地方)的 一种 输入流和输出流 文件在程序中是以流的形式来操作的 流:数据在数据源(文件)和程序(内存)之间经历的路径 输入流:数据从文件到内存的路径 输出流:数据从内存到文件的路径 os.File封装所有文件相关操作,File是一个结构体 文件基本操作 读操作 package main import ( "bufio" "fmt

  • C#开发Winform实现学生管理系统

    一.案例功能的实现 数据: --专业 create table ProfessionInfo ( ProfessionID int primary key identity(1,1), --专业编号 professionName varchar(50) not null unique --专业名称 ) --学生 create table StudentInfo ( StuID varchar(20) primary key, --学生学号 StuName varchar(50) not null

随机推荐