当前位置:   article > 正文

C#OOP CH09 文件操作_文本文件写入 需求说明 将定制的频道信息写入文本文件save.txt 写入格式

文本文件写入 需求说明 将定制的频道信息写入文本文件save.txt 写入格式

C#OOP CH09 文件操作

本章目标

  • 掌握文本文件的读写
  • 会进行文件和文件夹操作

1. 文件操作

1.1 如何读写文本文件

通常来讲,用C#程序读写一个文件需要以下五个基本步骤:

  1. 创建文件流
  2. 创建阅读器或者写入器
  3. 执行读写操作
  4. 关闭阅读器或者写入器
  5. 关闭文件流

代码演示如下:

写:

string path = this.txtPath.Text.Trim();
string context = this.txtContent.Text.Trim();
//创建文件流
FileStream fs = File.Create(path);
//创建写入流
StreamWriter sw = new StreamWriter(fs);
//执行写入操作
sw.Write(content);
//关闭写入流
sw.Close();
//关闭文件流
fs.Close();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

读:

string path = this.txtPath.Text.Trim();
//创建文件流
FileStream fs = File.OpenRead(path);
//创建读取流
StreamReader sr = new StreamReader(fs);
//执行读取操作
string content = sr.ReadToEnd();
this.txtContent.Text = content;
//关闭读取流
sr.Close();
//关闭文件流
fs.Close();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

简化步骤如下:

  1. 创建文件流
  2. 调用方法执行读写操作
  3. 关闭文件流

简化代码演示如下:

写:

using (FileStream fs = File.Create(path))
{
    byte[] info = new UTF8Encoding(true).GetBytes(content);
    fs.Write(info, 0, info.Length);
}
  • 1
  • 2
  • 3
  • 4
  • 5

读:

 using (FileStream fs = File.OpenRead(path))
 {
     byte[] b = new byte[1024];
     UTF8Encoding temp = new UTF8Encoding(true);
     StringBuilder sb = new StringBuilder();
     while (fs.Read(b, 0, b.Length) > 0)
     {
         sb.Append(temp.GetString(b));
     }
     this.txtContent.Text = sb.ToString();
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

1.2 创建文件流

  1. 创建文件流时,需要在它的构造函数中指定参数,参数说明如下:
    在这里插入图片描述

  2. 关闭文件流:
    写入结束后一定要关闭文件流 myfs.Close()。

1.3 创建写入器和读取器

  1. 文本文件的写入器和读取器方法如图所示:
    在这里插入图片描述

  2. 解决乱码问题:

    使用StreamReader读取文件中的中文文本,有时会产生乱码问题。这并不是因为C#语言有问题,而是因为不同文件编码格式可能不同。如果在编码时给文件读取器对象指定对应的编码格式,问题就迎刃而解了。

    以下代码展示了如何使用指定的编码格式:

    StreamReader sr = new StreamReader("文件名",Encoding.Default);
    
    • 1
    • 可以通过Encoding类的静态成员指定编码格式。例如:

      Encoding.UTF8:获取UTF-8格式的编码

      Encoding.Default:获取操作系统的当前编码

    • 也可以通过Encoding类的静态方法GetEncoding(string name) 指定字符编码,参数name必须是C#支持的编码名。例如:

      StreamReader sr = new StreamReader("文件名",Encoding.GetEncoding("GB2312"))
      
      • 1

      常见的编码可以参考官网:https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/character-encoding

  3. 使用写入器和读取器简化读写操作如下:

    写:

     using (StreamWriter sw = new StreamWriter(path,false,Encoding.UTF8))
     {
         sw.Write(this.txtContent.Text);
     }
    
    • 1
    • 2
    • 3
    • 4

    读:

    using (StreamReader sr = new StreamReader(path,Encoding.UTF8))
    {
        StringBuilder sb = new StringBuilder();
        while(sr.Peek() > -1)
        {
            sb.AppendLine(sr.ReadLine());
        }
        this.txtContent.Text = sb.ToString();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

1.4 网络电视精灵读写案例演示

需求:

将定制的频道信息写入文本文件

实现思路:

  1. 编写SaveAsText()方法,实现将定制的频道信息存入.txt文件
  2. 编写主窗体的FormClosed的事件,调用SaveAsText()方法

修改ChannelBase.cs,增加SaveAsText()方法,代码如下:

/// <summary>
///  频道管理类
/// </summary>
public class ChannelManager
{
   	//省略其他代码

    private string file = @"files/save.txt";

    private List<ChannelBase> list = new List<ChannelBase>();
    public List<ChannelBase> ChannelBaseList => list;
    public void SaveAsText()
    {
        try
        {
           using (StreamWriter writer = new StreamWriter(file,false,Encoding.UTF8))
            {
                list.ForEach(c => 
                             writer.WriteLine(c.ChannelType + "|" 
                                              + c.ChannelName + "|"  + c.Path));
            } 
        }
        catch(Exception e)
        {
            Console.WriteLine("写入文件异常,异常是:" + e.ToString());
        }            
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

编写主窗体的FormClosed的事件,调用SaveAsText()方法,关键代码如下:

private void FrmTV_FormClosed(object sender, FormClosedEventArgs e)
{
    //先清空频道集合中的数据
    channelManager.ChannelBaseList.Clear();
    //判断我电视台中是否有子节点
    if(this.tvChannel.Nodes[0].Nodes.Count > 0)
    {
        foreach (TreeNode node in tvChannel.Nodes[0].Nodes)
        {
            //将频道加入到集合中
            ChannelBase channel = node.Tag as ChannelBase;
            channelManager.ChannelBaseList.Add(channel);
        }
    }
    //写入文件
    channelManager.SaveText();
    //MessageBox.Show("写入成功");
    Application.Exit();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

需求:

读取定制频道信息

实现思路:

  • 从文本文件save.txt 读取定制的频道信息,并在主窗体运行时加载,最终实现定制频道信息的读取

修改ChannelManager.cs,增加ReadText方法,代码如下:

//读取文件
public void ReadText()
{
    try
    {
        if (!File.Exists(fileName)) return;//若文件不存在 则不执行读取操作
        using (StreamReader sr = new StreamReader(fileName,Encoding.UTF8))
        {
            while (sr.Peek() > -1)
            {
                string[] paramValue = sr.ReadLine().Split('|');
                ChannelBase channel = CreateChannelBase(paramValue[0],paramValue[1],paramValue[2]);
                ChannelBaseList.Add(channel);
            }
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

修改主窗体的窗体加载事件,代码如下:

public partial class FrmTV : Form
{
    ChannelManager channelManager = new ChannelManager();
    private void FrmTV_Load(object sender, EventArgs e)
    {
        //读取文件
        channelManager.ReadText();
        TreeNode rootNode = new TreeNode("我的电视台",0,1);
        this.tvChannels.Nodes.Add(rootNode);
        rootNode = new TreeNode("所有电视台",0,1);
        foreach (ChannelBase item in channelManager.FullChannels.Values)
        {
            TreeNode node = new TreeNode(item.ChannelName,0,1);
            node.Tag = item;
            node.Name = item.ChannleName;
            rootNode.Nodes.Add(node);
        }
        this.tvChannels.Nodes.Add(rootNode);
        //我的电视台
        if(channelManager.ChannelBaseList.Count > 0)
        {
            foreach (ChannelBase item in channelManager.ChannelBaseList)
            {
                TreeNode node = new TreeNode(item.ChannelName, 0, 1);
                node.Tag = item;
                node.Name = item.ChannleName;
                this.tvChannels.Nodes[0].Nodes.Add(node);
            }
        }
        this.tvChannels.ExpandAll();
    }
    //省略其他代码
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

2. 文件和目录操作

2.1 File 类

在这里插入图片描述

2.2 Directory 类

在这里插入图片描述

2.3 静态类与非静态类

在这里插入图片描述

2.4 静态成员与实例成员

在这里插入图片描述

2.4 FileInfo 类

在这里插入图片描述

2.5 DirectoryInfo 类

在这里插入图片描述

3. 文件的综合运用

开发小型资源管理器,可以浏览文件信息
在这里插入图片描述

3.1 读取目录下的子目录信息

先来完成第一个功能。操作目可以Directory类和DirectoryInfo类。由于资源管理器中的目录需要多次使用,所以优先选择DirectoryInfo类。如下示例所示:使用DirectoryInfo类获取D盘下的所有目录,并将目录信息显示在TreeView树状菜单中。

窗体类中,编写代码如下:

//窗体加载
private void FrmFile_Load(object sender, EventArgs e)
{
    //加载盘符
    LoadDrivers();
}
public void LoadDrivers()
{
    string path = @"D:\";
    TreeNode node = new TreeNode(path);
    node.Tag = path;
    this.tvDic.Nodes.Add(node);
}
//节点选中改变事件
private void tvDic_AfterSelect(object sender, TreeViewEventArgs e)
{
    //获取当前选中的节点
    TreeNode node = this.tvDic.SelectedNode;
    //填充treeview
    BindInfo(node);
}
//将目录绑定到TreeView中
public void BindInfo(TreeNode node)
{
    //创建目录对象
    DirectoryInfo directoryInfo = new DirectoryInfo(node.Tag.ToString());
    //加载子目录
    DirectoryInfo[] dirs = directoryInfo.GetDirectories();
    dirs.ForEach(dir =>
                 {
                     TreeNode temp = new TreeNode(dir.Name);
                     temp.Tag = dir.FullName;
                     node.Nodes.Add(temp);
                 });
    //foreach (DirectoryInfo dir in dirs)
    //{
    //    TreeNode temp = new TreeNode(dir.Name);
    //    temp.Tag = dir.FullName;
    //    node.Nodes.Add(temp);
    //}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

创建MyExMethod类,扩展ForEach方法,代码如下:

public static class MyExMethods
{
    public static void ForEach<T>(this IEnumerable<T> source,Action<T> action)
    {
        foreach (var item in source)
        {
            action(item);
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.2 读取目录下的文件信息

读取文件信息的方式和读取目录信息的方式大同小异。为了表示方便,我们定义一个MyFile类来存储文件信息。MyFile类的属性如下表所示:

属性类型说明
FileLengthfloat文件长度,以KB为单位
FileNamestring文件名
FilePathstring文件路径
FileTypestring文件类型

创建MyFile类,封装文件的各种信息,代码如下:

public class MyFile
{
    public string FileName { get; set; }//文件名
    private float fileLength;
    public float FileLength//文件大小
    {
        get
        {
            return fileLength;
        }
        set
        {
            fileLength = (float)Math.Round(value / 1024, 2);
        }
    }
    public string FileType { get; set; }//文件类型
    public string FilePath { get; set; }//文件路径
    public MyFile(string fileName, float fileLength, string fileType, string filePath)
    {
        this.FileName = fileName;
        this.FileLength = fileLength;
        this.FileType = fileType;
        this.FilePath = filePath;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

单击树状菜单上的目录节点,绑定该目录下文件的基本信息。代码如下:

//将目录绑定到TreeView中 并且加载目录下的子文件
public void BindInfo(TreeNode node)
{
    //创建目录对象
    DirectoryInfo directoryInfo = new DirectoryInfo(node.Tag.ToString());
    //加载子目录
    DirectoryInfo[] dirs = directoryInfo.GetDirectories();
    dirs.ForEach(dir =>
                 {
                     TreeNode temp = new TreeNode(dir.Name);
                     temp.Tag = dir.FullName;
                     node.Nodes.Add(temp);
                 });
    //foreach (DirectoryInfo dir in dirs)
    //{
    //    TreeNode temp = new TreeNode(dir.Name);
    //    temp.Tag = dir.FullName;
    //    node.Nodes.Add(temp);
    //}
    //加载子文件
    FileInfo[] fileInfo =  directoryInfo.GetFiles();
    List<MyFile> files = new List<MyFile>();
    fileInfo.ForEach(file =>files.Add(
        new MyFile(file.Name, file.Length, file.Extension, file.FullName)));
    //foreach (FileInfo file in fileInfo)
    //{
    //    MyFile myFile = new MyFile();
    //    myFile.FileName = file.Name;
    //    myFile.FileLength = file.Length;
    //    myFile.FileType = file.Extension;
    //    myFile.FilePath = file.FullName;
    //    files.Add(myFile);
    //}
    //绑定ListView
    BindListView(files);
}
//绑定ListView
public void BindListView(List<MyFile> files)
{
    this.lvFile.Items.Clear();
    files.ForEach(item =>
                  {
                      ListViewItem listViewItem = new ListViewItem(item.FileName);
                      listViewItem.SubItems.Add(item.FileLength.ToString());
                      listViewItem.SubItems.Add(item.FileType);
                      listViewItem.SubItems.Add(item.FilePath);
                      this.lvFile.Items.Add(listViewItem);
                  });
    //foreach (MyFile item in files)
    //{
    //    ListViewItem listViewItem = new ListViewItem(item.FileName);
    //    listViewItem.SubItems.Add(item.FileLength.ToString());
    //    listViewItem.SubItems.Add(item.FileType);
    //    listViewItem.SubItems.Add(item.FilePath);
    //    this.lvFile.Items.Add(listViewItem);
    //}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

3.3 实现文件复制

需求说明

  • 完善小型资源管理器,实现文件复制
  • 支持用户从“浏览文件夹”对话框选定目标位置
    在这里插入图片描述

实现思路

  • 打开“浏览文件夹”,并获得选择的存储路径,实现代码如下
//复制
private void tsmiCopy_Click(object sender, EventArgs e)
{
    if (this.lvFile.SelectedItems.Count == 0) return;
    FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
    DialogResult result = folderBrowserDialog.ShowDialog();
    if (result == DialogResult.No) return;
    File.Copy(this.lvFile.SelectedItems[0].SubItems[3].Text,
              folderBrowserDialog.SelectedPath + "\\" + this.lvFile.SelectedItems[0].Text);
    MessageBox.Show("复制成功");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

3.4 实现文件删除

需求说明

  • 完善小型资源管理器,实现文件删除,并刷新ListView显示
    在这里插入图片描述
    实现思路

  • 可以使用File类的Delete(string filePath)方法,实现代码如下:

//删除
private void tsmiDel_Click(object sender, EventArgs e)
{
    if (this.lvFile.SelectedItems.Count == 0) return;
    DialogResult result = MessageBox.Show("确定要删除该文件吗?", "提示", MessageBoxButtons.YesNo);
    if (result == DialogResult.No) return;
    File.Delete(this.lvFile.SelectedItems[0].SubItems[3].Text);
    MessageBox.Show("删除成功");
    //刷新
    this.lvFile.SelectedItems[0].Remove();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/417340
推荐阅读
相关标签
  

闽ICP备14008679号