在C#中是否有一种简单的方法来读取属性文件,该文件在单独的行上包含每个属性,后跟等号和值,如下所示:
ServerName=prod-srv1 Port=8888 CustomProperty=Any value
在Java中,Properties类可以轻松处理此解析:
Properties myProperties=new Properties(); FileInputStream fis = new FileInputStream (new File("CustomProps.properties")); myProperties.load(fis); System.out.println(myProperties.getProperty("ServerName")); System.out.println(myProperties.getProperty("CustomProperty"));
我可以轻松地在C#中加载文件并解析每一行,但是有没有内置的方法来轻松获取属性而无需解析密钥名称和等号本身?我发现的C#信息似乎总是支持XML,但这是一个我无法控制的现有文件,我宁愿将其保留为现有格式,因为需要更多时间让其他团队将其更改为XML而不是解析现有的文件.
没有内置的支持.
你必须自己制作"INIFileReader".也许是这样的?
var data = new Dictionary(); foreach (var row in File.ReadAllLines(PATH_TO_FILE)) data.Add(row.Split('=')[0], string.Join("=",row.Split('=').Skip(1).ToArray())); Console.WriteLine(data["ServerName"]);
编辑:更新以反映保罗的评论.
大多数Java".properties"文件可以通过假设"="是分隔符来拆分 - 但格式要复杂得多,并且允许在属性名称或值中嵌入空格,等号,换行符和任何Unicode字符.
我需要为C#应用程序加载一些Java属性,所以我已经使用与Java版本相同的方法实现了JavaProperties.cs以正确读取和写入".properties"格式化文件 - 您可以在http://www.kajabity找到它.com/index.php/2009/06/loading-java-properties-files-in-csharp /.
在那里,你会找到一个zip文件,其中包含该类的C#源代码以及我测试过的一些示例属性文件.
请享用!
最后一堂课.谢谢@eXXL.
public class Properties { private Dictionarylist; private String filename; public Properties(String file) { reload(file); } public String get(String field, String defValue) { return (get(field) == null) ? (defValue) : (get(field)); } public String get(String field) { return (list.ContainsKey(field))?(list[field]):(null); } public void set(String field, Object value) { if (!list.ContainsKey(field)) list.Add(field, value.ToString()); else list[field] = value.ToString(); } public void Save() { Save(this.filename); } public void Save(String filename) { this.filename = filename; if (!System.IO.File.Exists(filename)) System.IO.File.Create(filename); System.IO.StreamWriter file = new System.IO.StreamWriter(filename); foreach(String prop in list.Keys.ToArray()) if (!String.IsNullOrWhiteSpace(list[prop])) file.WriteLine(prop + "=" + list[prop]); file.Close(); } public void reload() { reload(this.filename); } public void reload(String filename) { this.filename = filename; list = new Dictionary (); if (System.IO.File.Exists(filename)) loadFromFile(filename); else System.IO.File.Create(filename); } private void loadFromFile(String file) { foreach (String line in System.IO.File.ReadAllLines(file)) { if ((!String.IsNullOrEmpty(line)) && (!line.StartsWith(";")) && (!line.StartsWith("#")) && (!line.StartsWith("'")) && (line.Contains('='))) { int index = line.IndexOf('='); String key = line.Substring(0, index).Trim(); String value = line.Substring(index + 1).Trim(); if ((value.StartsWith("\"") && value.EndsWith("\"")) || (value.StartsWith("'") && value.EndsWith("'"))) { value = value.Substring(1, value.Length - 2); } try { //ignore dublicates list.Add(key, value); } catch { } } } } }
样品用途:
//load Properties config = new Properties(fileConfig); //get value whith default value com_port.Text = config.get("com_port", "1"); //set value config.set("com_port", com_port.Text); //save config.Save()
我写了一个方法,允许在文件中使用emty行,outzmenting和quoting.
例子:
var1 ="value1"
var2 ='value2'
'var3 = outcommented
; var4 =也取消评论
这是方法:
public static IDictionary ReadDictionaryFile(string fileName) { Dictionarydictionary = new Dictionary (); foreach (string line in File.ReadAllLines(fileName)) { if ((!string.IsNullOrEmpty(line)) && (!line.StartsWith(";")) && (!line.StartsWith("#")) && (!line.StartsWith("'")) && (line.Contains('='))) { int index = line.IndexOf('='); string key = line.Substring(0, index).Trim(); string value = line.Substring(index + 1).Trim(); if ((value.StartsWith("\"") && value.EndsWith("\"")) || (value.StartsWith("'") && value.EndsWith("'"))) { value = value.Substring(1, value.Length - 2); } dictionary.Add(key, value); } } return dictionary; }
旧问题(2009年1月)的另一个答案(2018年1月)。
Java属性文件的规范在的JavaDoc中进行了描述java.util.Properties.load(java.io.Reader)
。一个问题是规范比我们可能给人的第一印象要复杂一些。另一个问题是,一些答案在这里任意添加额外的规格-例如,;
与'
被视为注释行首发,但他们不应该。属性值周围的双引号/单引号已删除,但不应删除。
以下是要考虑的要点。
有两种线,自然线和逻辑线。
自然行由终止\n
,\r
,\r\n
或流的结束。
通过使用反斜杠字符将行终止符序列转义,可以将逻辑行分布在几条相邻的自然行之间\
。
逻辑行中第二条自然线和其后自然线开头的所有空白都将被丢弃。
白空间是空间(,
\u0020
),标签(\t
,\u0009
)和形式进料(\f
,\u000C
)。
正如规范中明确指出的那样,“仅检查行终止符序列前面的字符来决定是否终止行终止符是不够的;要逃逸的行终止符必须有奇数个连续的反斜杠。输入是从左到右处理的,在转义符处理后,行终止符(或其他地方)对n个反斜杠进行编码之前,非零偶数个2n个连续的反斜杠。”
=
用作键和值之间的分隔符。
:
也用作键和值之间的分隔符。
键和值之间的分隔符可以省略。
注释行以#
或!
作为其第一个非空白字符,表示在#
或之前的前导空格!
。
注释行不能扩展到下一个自然行,即使其行终止符前面有\
。
如规范中明确指出的那样=
,,:
和如果空格被反斜杠转义,则可以将它们嵌入到键中。
甚至可以使用\r
和\n
转义序列包括行终止符。
如果省略值,则将空字符串用作值。
\uxxxx
用于表示Unicode字符。
无效的转义字符之前的反斜杠字符不会被视为错误;它被默默地丢弃了。
因此,例如,if test.properties
具有以下内容:
# A comment line that starts with '#'. # This is a comment line having leading white spaces. ! A comment line that starts with '!'. key1=value1 key2 : value2 key3 value3 key\ 4=value\ 4 \u006B\u0065\u00795=\u0076\u0061\u006c\u0075\u00655 \k\e\y\6=\v\a\lu\e\6 \:\ \= = \\colon\\space\\equal
应该将其解释为以下键值对。
+------+--------------------+ | KEY | VALUE | +------+--------------------+ | key1 | value1 | | key2 | value2 | | key3 | value3 | | key4 | value4 | | key5 | value5 | | key6 | value6 | | : = | \colon\space\equal | +------+--------------------+
PropertiesLoader
Authlete.Authlete NuGet包中的类可以解释规范的格式。下面的示例代码:
# A comment line that starts with '#'. # This is a comment line having leading white spaces. ! A comment line that starts with '!'. key1=value1 key2 : value2 key3 value3 key\ 4=value\ 4 \u006B\u0065\u00795=\u0076\u0061\u006c\u0075\u00655 \k\e\y\6=\v\a\lu\e\6 \:\ \= = \\colon\\space\\equal
将生成以下输出:
key1 = value1 key2 = value2 key3 = value3 key4 = value4 key5 = value5 key6 = value6 : = = \colon\space\equal
Java中的等效示例如下:
+------+--------------------+ | KEY | VALUE | +------+--------------------+ | key1 | value1 | | key2 | value2 | | key3 | value3 | | key4 | value4 | | key5 | value5 | | key6 | value6 | | : = | \colon\space\equal | +------+--------------------+
PropertiesLoader.cs
可以在authlete-csharp中找到源代码。的xUnit测试用PropertiesLoader
编写PropertiesLoaderTest.cs
。