赞
踩
通常来讲,用C#程序读写一个文件需要以下五个基本步骤:
代码演示如下:
写:
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();
读:
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();
简化步骤如下:
简化代码演示如下:
写:
using (FileStream fs = File.Create(path))
{
byte[] info = new UTF8Encoding(true).GetBytes(content);
fs.Write(info, 0, info.Length);
}
读:
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();
}
创建文件流时,需要在它的构造函数中指定参数,参数说明如下:
关闭文件流:
写入结束后一定要关闭文件流 myfs.Close()。
文本文件的写入器和读取器方法如图所示:
解决乱码问题:
使用StreamReader读取文件中的中文文本,有时会产生乱码问题。这并不是因为C#语言有问题,而是因为不同文件编码格式可能不同。如果在编码时给文件读取器对象指定对应的编码格式,问题就迎刃而解了。
以下代码展示了如何使用指定的编码格式:
StreamReader sr = new StreamReader("文件名",Encoding.Default);
可以通过Encoding类的静态成员指定编码格式。例如:
Encoding.UTF8:获取UTF-8格式的编码
Encoding.Default:获取操作系统的当前编码
也可以通过Encoding类的静态方法GetEncoding(string name) 指定字符编码,参数name必须是C#支持的编码名。例如:
StreamReader sr = new StreamReader("文件名",Encoding.GetEncoding("GB2312"))
常见的编码可以参考官网:https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/character-encoding
使用写入器和读取器简化读写操作如下:
写:
using (StreamWriter sw = new StreamWriter(path,false,Encoding.UTF8))
{
sw.Write(this.txtContent.Text);
}
读:
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();
}
需求:
将定制的频道信息写入文本文件
实现思路:
修改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()); } } }
编写主窗体的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(); }
需求:
读取定制频道信息
实现思路:
修改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()); } }
修改主窗体的窗体加载事件,代码如下:
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(); } //省略其他代码 }
开发小型资源管理器,可以浏览文件信息
先来完成第一个功能。操作目可以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); //} }
创建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);
}
}
}
读取文件信息的方式和读取目录信息的方式大同小异。为了表示方便,我们定义一个MyFile类来存储文件信息。MyFile类的属性如下表所示:
属性 | 类型 | 说明 |
---|---|---|
FileLength | float | 文件长度,以KB为单位 |
FileName | string | 文件名 |
FilePath | string | 文件路径 |
FileType | string | 文件类型 |
创建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; } }
单击树状菜单上的目录节点,绑定该目录下文件的基本信息。代码如下:
//将目录绑定到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); //} }
需求说明
实现思路
//复制
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("复制成功");
}
需求说明
完善小型资源管理器,实现文件删除,并刷新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();
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。