C#实现配置文件的读取

前言:配置文件这个词对于大家来说那是相当熟悉不过啦!如果你经常在Java中操作配置文件的话,相信你会对Java里的Properties类能够熟练操作啦。
前几天我在C#也有操作配置文件需求,但是通过查询一轮下来之后,发现C#里面的配置文件是xml类型的,觉得比较麻烦,于是决定写一个操作纯键值对的配置文件工具类,
造个轮子!


大致思路

  • 读取配置文件:根据相对应的路径查找配置文件
  • 对键值进行增删改查:根据键对配置文件进行操作
  • 写入配置文件:将操作后的配置文件进行更新

前期普及

参考Java里的Properties类一些方法实现

定义:

  • Properties:Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串

方法:

  • void load(InputStream inStream):从输入流中读取属性列表(键和元素对)
  • String getProperty(String key):用指定的键在此属性列表中搜索属性
  • Object setProperty(String key, String value):调用 Hashtable 的方法 put
  • void store(Writer writer, String comments):以适合使用 load(Reader) 方法的格式,将此 Properties 表中的属性列表(键和元素对)写入输出字符

1、读取配置文件

通过加载配置文件,然后保存到C#的集合中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/// <summary>
/// 读取文件,并用集合将配置信息保存起来
/// </summary>
/// <param name="path">文件路径</param>
/// <param name="properties">配置文件信息</param>
/// <returns></returns>
private Dictionary<string, string> Read(string path, Dictionary properties)
{
// 注意问题:读写文件时提示文件正由另一进程使用,因此该进程无法访问该文件
FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// 创建读取流对象,注意编码问题,统一使用UTF-8编码即可
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
// 按行读取文件,并将文件信息写入集合中
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains("="))
{
string[] temps = line.Split('=');
properties.Add(temps[0], temps[1]);
}
}
return properties;
}

注意事项:

  • 1、文件路径的正确性:确保文件路径的正确性,可以使用Console.WriteLine(path);查看路径的输出是否正确
  • 2、文件的使用正确性:如果在根据路径读取文件的时候没有添加FileMode.Open, FileAccess.Read, FileShare.ReadWrite参数的时候,会出现读写文件时提示文件正由另一进程使用,因此该进程无法访问该文件
    的错误

2、对配置文件进行操作

通过步骤1我们已经得到配置文件的信息,现在我们来修改配置文件中的value值吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/// <summary>
/// 根据字段名称修改字段内容
/// </summary>
/// <param name="properties">配置文件信息集合</param>
/// <param name="fieldName">要修改的字段名称</param>
/// <param name="fieldValue">修改后的字段值</param>
/// <returns></returns>
public bool SetProperties(Dictionary properties, string fieldName, string fieldValue)
{
// 1.查找配置文件是否存在
if (!properties.ContainsKey(fieldName)) throw new Exception(string.Format("不存在键 {0} 请检查重试!", fieldName));
// 2.修改文件内容
properties.Remove(fieldName);
properties.Add(fieldName, fieldValue);
}

注意事项:

  • 1、在C#里面如果对集合已存在的键,再次添加相同键的时候会报错,如果要修改相同键不同值得时候,应该先把之前的键删除,再添加

3、将操作后的配置文件信息写入文件

通过步骤2我们已经对配置文件进行操作,此时对操作后的信息再次写入文件中

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
/// <summary>
/// 写入文件
/// </summary>
/// <param name="path">写入文件的路径</param>
/// <returns></returns>
private bool Save(string path)
{
bool flag = true;
try
{
// 根据路径创建文件流
FileStream stream = new FileStream(path, FileMode.Create);
// 使用流向文件里面写内容,注意编码问题,统一使用UTF-8编码即可
StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
// 开始将配置信息逐行写入文件
foreach (var item in properties)
{
writer.WriteLine(string.Format("{0}={1}", item.Key, item.Value));
}
// 清空缓冲区
writer.Flush();
// 关闭流
stream.Close();
// 此处不能关闭writer流,否则会出现"System.ObjectDisposedException 无法访问已关闭的文件"异常
//writer.Close();
}
catch
{
flag = false;
}
return flag;
}

注意事项:

  • 1、编码问题:在对文件进行操作的时候,编码是我们应该要重视的问题
  • 2、缓冲区:在对文件进行操作完毕后,应该刷新一下缓冲区

4、最终测试

现在整合三个方法,实现一个修改配置文件的工具类,达到类似Java中的Properties类的效果

“配置文件”

name=hunter

hobby=coding

工具类如下

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/// <summary>
/// 读写配置文件工具
/// </summary>
class FileUtils
{
/// <summary>
/// 保存配置文件信息
/// </summary>
Dictionary<string, string> properties;
/// <summary>
/// 文件路径
/// </summary>
string path;
/// <summary>
/// 读取文件,并用集合将配置信息保存起来
/// </summary>
/// <returns>配置文件信息集合</returns>
private Dictionary<string, string> Read()
{
path = path.Substring(1);
properties = new Dictionary<string, string>();
// 注意问题:读写文件时提示文件正由另一进程使用,因此该进程无法访问该文件
FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
// 创建读取流对象,注意编码问题,统一使用UTF-8编码即可
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
// 按行读取文件,并将文件信息写入集合中
string line;
while ((line = reader.ReadLine()) != null)
{
if (line.Contains("="))
{
string[] temps = line.Split('=');
properties.Add(temps[0], temps[1]);
}
}
return properties;
}
/// <summary>
/// 根据字段名称修改字段内容
/// </summary>
/// <param name="path">要修改文件的路径</param>
/// <param name="fieldName">要修改的字段名称</param>
/// <param name="fieldValue">修改后的字段值</param>
/// <returns></returns>
public bool SetProperties(string path, string fieldName, string fieldValue)
{
// 0.初始化变量
this.path = path;
// 1.读取配置文件
properties = Read();
// 2.查找配置文件是否存在
if (!properties.ContainsKey(fieldName)) throw new Exception(string.Format("不存在键 {0} 请检查重试!", fieldName));
// 3.修改文件内容
properties.Remove(fieldName);
properties.Add(fieldName, fieldValue);
// 4.写入文件
bool isSave = Save();
return isSave;
}
/// <summary>
/// 将配置文件写入文件
/// </summary>
/// <returns>是否写入成功</returns>
private bool Save()
{
bool flag = true;
try
{
// 根据路径创建文件流
FileStream stream = new FileStream(path, FileMode.Create);
// 使用流向文件里面写内容,注意编码问题,统一使用UTF-8编码即可
StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
// 开始将配置信息逐行写入文件
foreach (var item in properties)
{
writer.WriteLine(string.Format("{0}={1}", item.Key, item.Value));
}
// 清空缓冲区
writer.Flush();
// 关闭流
stream.Close();
// 此处不能关闭writer流,否则会出现"System.ObjectDisposedException 无法访问已关闭的文件"异常
//writer.Close();
}
catch
{
flag = false;
}
return flag;
}
}

调用结果

1
2
3
4
5
6
private void ChangeProperties()
{
PropertiesUtils utils = new PropertiesUtils();
bool flag = utils.SetProperties(@"‪d:\test.txt", "name", "Hunter");
Console.WriteLine("是否修改:" + flag);
}

此时查看配置文件的name属性时,已经由原来的hunter变成Hunter了,说明我们已经成功修改配置文件

本文小结

本文虽然是一个小小的造轮子,但是在造轮子的过程中学习到了很多想不到的收获,能够快速帮助我们成长起来,计算机是门应用学,我们应该多去实践操作!
这篇文章只是提供了如何根据属性名修改相对应的属性值,当然你还有兴趣的话,完全可以增加对配置文件的功能,
此外,对于此次造轮子情况得出一个结论,凡是设计操作IO流的情况我们都应该要注意编码问题


版权声明:本文为博主原创文章,转载请注明出处http://hunterblog.cn/ 和作者:Hunter,谢谢支持。