关于 C# 读取/写入 配置文件,有什么简单的办法?

BlackHouse
小黑屋 2019-08-20 字数 575

我希望有个简单的读取XML配置文件的办法,类似于 Config.Settings["NodeRoot/NodeName/NodeSubName"].Value,而不需要自己创建XmlDocument然后去解析文件。

而且可读、可写、文件在exe之外,改了配置不需要重新编译。

网上搜索了半天,没有找到合适的办法。

有几个疑问:

1、App.config 和 Settings.settings 的区别是什么?前者是exe外部文件,后者是打包的内部的,对吗?

2、用 ConfigurationManager 读取 App.config 的时候,为什么只有 AppSettings 和 ConnectionStrings两个方法?我不能自定义更多的配置节点吗?

3、ConfigurationManager.AppSettings.Add 或 Set 报错,提示“该配置是只读的”,我怎么写入配置文件呢?

DotNET Microsoft.NET技术
1 个Like
30 个回复
yemingzhu
yemingzhu 2019-08-20

远程配置中心

【 在 BlackHouse 的大作中提到: 】

: 我希望有个简单的读取XML配置文件的办法,类似于 Config.Settings["NodeRoot/NodeName/NodeSubName"].Value,而不需要自己创建XmlDocument然后去解析文件。

: 而且可读、可写、文件在exe之外,改了配置不需要重新编译。

: 网上搜索了半天,没有找到合适的办法。

: ...................

yemingzhu
yemingzhu 2019-08-20

可以自己写一个 就跟Apollo之类的

【 在 BlackHouse 的大作中提到: 】

: 我希望有个简单的读取XML配置文件的办法,类似于 Config.Settings["NodeRoot/NodeName/NodeSubName"].Value,而不需要自己创建XmlDocument然后去解析文件。

: 而且可读、可写、文件在exe之外,改了配置不需要重新编译。

: 网上搜索了半天,没有找到合适的办法。

: ...................

SPQR
黑猫警长 2019-08-20

直接用 ini 不好吗?

【 在 BlackHouse (小黑屋) 的大作中提到: 】

: 我希望有个简单的读取XML配置文件的办法,类似于 Config.Settings["NodeRoot/NodeName/NodeSubName"].Value,而不需要自己创建XmlDocument然后去解析文件。

: 而且可读、可写、文件在exe之外,改了配置不需要重新编译。

: 网上搜索了半天,没有找到合适的办法。

: ...................

a0123456789q
a0123456789q 2019-08-21

当然用 ConfigurationManager.

1.App.config会编译到Assembly的旁边. Settings会存储在操作系统给用户指定的位置。

App.config只读(但你可以手动编辑,下次启动后生效),Settings用App.config初始化后可变。

2.当然可以配置。我推荐你在每个Dll的Settings里操作,然后调用每个Dll的Settings实例

3. 参见"1", App.config is readonly.

【 在 BlackHouse (小黑屋) 的大作中提到: 】

: 我希望有个简单的读取XML配置文件的办法,类似于 Config.Settings["NodeRoot/NodeName/NodeSubName"].Value,而不需要自己创建XmlDocument然后去解析文件。

: 而且可读、可写、文件在exe之外,改了配置不需要重新编译。

: 网上搜索了半天,没有找到合适的办法。

: ...................

vmx
战斗劳动妇男王小桃 2019-08-21

App.Config应该说是readonce吧,程序是可以写入的,只不过要下一次才能读到了。

【 在 a0123456789q (a0123456789q) 的大作中提到: 】

: 当然用 ConfigurationManager.

: 1.App.config会编译到Assembly的旁边. Settings会存储在操作系统给用户指定的位置。

: App.config只读(但你可以手动编辑,下次启动后生效),Settings用App.config初始化后可变。

: ...................

a0123456789q
a0123456789q 2019-08-21

不能写。

【 在 vmx (战斗劳动妇男王小桃) 的大作中提到: 】

: App.Config应该说是readonce吧,程序是可以写入的,只不过要下一次才能读到了。

BlackHouse
小黑屋 2019-08-21

所以我没搞明白,.NET搞了那么多配置文件,各种manager各种disigner,

结果连runtime修改配置都这么麻烦,还不如ini简单实惠,那他们搞这个意义何在?

【 在 SPQR 的大作中提到: 】

: 直接用 ini 不好吗?

KEILLY
米饭 2019-08-21

https://www.cnblogs.com/luna-hehe/p/9104748.html

sectionGroup 自定义配置节组

configSections自定义配置节

这可能是你要的。。

微软应该提供了一些的,不只是你提到的那2个最常用节点

“只读”———— .net 2.0之前是可以修改的。后来才改成“只读”文件。

【 在 BlackHouse 的大作中提到: 】

: 网上搜索了半天,没有找到合适的办法。

: ...................

a0123456789q
a0123456789q 2019-08-21

也可能你没搞明白。

app.config是你开发和部署时候设定的。

setting是给软件的使用者用的。

【 在 BlackHouse (小黑屋) 的大作中提到: 】

: 所以我没搞明白,.NET搞了那么多配置文件,各种manager各种disigner,

: 结果连runtime修改配置都这么麻烦,还不如ini简单实惠,那他们搞这个意义何在?

: :

rexxie
kingofcrabs 2019-08-26

配置放个类,直接Serialize成xml,初始化时Deserialize,

Serialize是泛型的,我项目中抠出来的,你看下。

public class SerializeHelper

{

static public void Save<T>(T setting, string sFile) where T : class

{

int pos = sFile.LastIndexOf("\\");

string sDir = sFile.Substring(0, pos);

if (!Directory.Exists(sDir))

Directory.CreateDirectory(sDir);

if (File.Exists(sFile))

File.Delete(sFile);

XmlSerializer xs = new XmlSerializer(typeof(T));

Stream stream = new FileStream(sFile, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.ReadWrite);

xs.Serialize(stream, setting);

stream.Close();

}

static public T Load<T>(string sFile) where T : class,new()

{

Object obj = new object();

if (!File.Exists(sFile))

return new T();

Stream stream = new FileStream(sFile, FileMode.Open, FileAccess.Read, FileShare.Read);

XmlSerializer xs = new XmlSerializer(typeof(T));

obj = xs.Deserialize(stream) as T;

stream.Close();

return (T)obj;

}

}

【 在 BlackHouse 的大作中提到: 】

: 所以我没搞明白,.NET搞了那么多配置文件,各种manager各种disigner,

: 结果连runtime修改配置都这么麻烦,还不如ini简单实惠,那他们搞这个意义何在?

: :

a0123456789q
a0123456789q 2019-08-26

厉害。

不过楼主的需求我建议 还是 用 框架 给的 配置搞法,因为:

1)每个用户的存储位置不一样

【 在 rexxie (kingofcrabs) 的大作中提到: 】

: 配置放个类,直接Serialize成xml,初始化时Deserialize,

: Serialize是泛型的,我项目中抠出来的,你看下。

:  public class SerializeHelper

: ...................

rexxie
kingofcrabs 2019-08-26

过奖,这太常见了,

我只是说c#的配置比ini还是要牛逼的,ini多麻烦的。

【 在 a0123456789q 的大作中提到: 】

: 厉害。

: 不过楼主的需求我建议 还是 用 框架 给的 配置搞法,因为:

: 1)每个用户的存储位置不一样

: ...................

bigfeet1983
努力的大脚 2019-08-26

我很不喜欢自带的那个app.config

还不如自己弄一个json序列化和反序列化

【 在 BlackHouse (小黑屋) 的大作中提到: 】

: 我希望有个简单的读取XML配置文件的办法,类似于 Config.Settings["NodeRoot/NodeName/NodeSubName"].Value,而不需要自己创建XmlDocument然后去解析文件。

: 而且可读、可写、文件在exe之外,改了配置不需要重新编译。

: 网上搜索了半天,没有找到合适的办法。

: ...................

mingqiao
荻芦苍苍 2019-08-27

搭车问一个相关的问题

程序的配置文件,通常要给一个设置的界面,有没有好用的从Config(其他的也行ini,json,xml)到界面的库或者自动化工具可用?以前都是手动一个一个自己写,是不是有点蠢?

求教。

【 在 BlackHouse (小黑屋) 的大作中提到: 】

: 我希望有个简单的读取XML配置文件的办法,类似于 Config.Settings["NodeRoot/NodeName/NodeSubName"].Value,而不需要自己创建XmlDocument然后去解析文件。

: 而且可读、可写、文件在exe之外,改了配置不需要重新编译。

: 网上搜索了半天,没有找到合适的办法。

: ...................

rexxie
kingofcrabs 2019-08-27

我一般会用反射将class里面的public 属性读出来放到Dictionary<string,string>里面,

然后将Dictionary显示在listview中,改过后再将Dictionary 写回到对象,只支持bool,int,double,string。我平时用也够了。

internal void SetSetting(Object obj, Dictionary<string, string> settings)

{

var fieldsType = obj.GetType();

Dictionary<string, string> dict = new Dictionary<string, string>();

FieldInfo[] fields = fieldsType.GetFields(BindingFlags.Public

| BindingFlags.Instance);

for (int i = 0; i < fields.Length; i++)

{

//settings[fields[i].SetValue()

string key = fields[i].Name;

object subObj = ParseString(settings[key]);

fields[i].SetValue(obj, subObj);

}

}

object ParseString(string s)

{

bool result = false;

double dVal = 0;

int val = 0;

if (bool.TryParse(s, out result))

{

return result;

}

else if (int.TryParse(s, out val))

{

return val;

}

else if (double.TryParse(s, out dVal))

{

return dVal;

}

return s;

}

internal Dictionary<string, string> GetSetting(Object settings)

{

var fieldsType = settings.GetType();

Dictionary<string, string> dict = new Dictionary<string, string>();

FieldInfo[] fields = fieldsType.GetFields(BindingFlags.Public

| BindingFlags.Instance);

for (int i = 0; i < fields.Length; i++)

{

dict.Add(fields[i].Name, fields[i].GetValue(settings).ToString());

}

return dict;

}

object ParseString(string s)

{

bool result = false;

double dVal = 0;

int val = 0;

if (bool.TryParse(s, out result))

{

return result;

}

else if (int.TryParse(s, out val))

{

return val;

}

else if (double.TryParse(s, out dVal))

{

return dVal;

}

return s;

}

【 在 mingqiao 的大作中提到: 】

: 搭车问一个相关的问题

: 程序的配置文件,通常要给一个设置的界面,有没有好用的从Config(其他的也行ini,json,xml)到界面的库或者自动化工具可用?以前都是手动一个一个自己写,是不是有点蠢?

: 求教。

: ...................

mingqiao
荻芦苍苍 2019-08-27

学习了。。我试试

【 在 rexxie (kingofcrabs) 的大作中提到: 】

: 我一般会用反射将class里面的public 属性读出来放到Dictionary<string,string>里面,

: 然后将Dictionary显示在listview中,改过后再将Dictionary 写回到对象,只支持bool,int,double,string。我平时用也够了。

:    internal void SetSetting(Object obj, Dictionary<string, string> settings)

: ...................

ShinyWong
Shiny Wong 2019-08-27

不限制设置的数值范围的话,可以将 ApplicationSettingsBase 加载到 WinForms

的 PropertyGrid 控件里:

https://stackoverflow.com/a/12042754

【 在 mingqiao 的大作中提到: 】

: 搭车问一个相关的问题

: 程序的配置文件,通常要给一个设置的界面,有没有好用的从Config(其他的也行ini,json,xml)到界面的库或者自动化工具可用?以前都是手动一个一个自己写,是不是有点蠢?

: 求教。

: ...................

bigfeet1983
努力的大脚 2019-08-28

git上记得有个wpf的工具可以玩

其实这些都是对对象的修改

至于对象序列化成xml还是json都无所谓的

【 在 mingqiao (荻芦苍苍) 的大作中提到: 】

: 搭车问一个相关的问题

: 程序的配置文件,通常要给一个设置的界面,有没有好用的从Config(其他的也行ini,json,xml)到界面的库或者自动化工具可用?以前都是手动一个一个自己写,是不是有点蠢?

: 求教。

mingqiao
荻芦苍苍 2019-08-29

能给个关键字吗我去查查,谢谢大神,哈哈

【 在 bigfeet1983 (努力的大脚) 的大作中提到: 】

: git上记得有个wpf的工具可以玩

: 其实这些都是对对象的修改

: 至于对象序列化成xml还是json都无所谓的

: ...................