.NET能否加载和parsing一个相当于Java Properties类的属性文件?
有没有一种简单的方法在C#中读取一个属性文件,每个属性在一个单独的行后跟一个等号和值,如下所示:
ServerName=prod-srv1 Port=8888 CustomProperty=Any value
在Java中,Properties类很容易处理这个parsing:
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#中的文件,并parsing每一行,但有没有一种内置的方式来轻松地获得一个属性,而不必parsing出自己的键名和等号? 我发现的C#信息似乎总是支持XML,但是这是一个我不能控制的现有文件,我宁愿将它保留在现有格式中,因为需要更多时间让另一个团队将其更改为XML比parsing现有的文件。
不,没有内置的支持。
你必须制作你自己的“INIFileReader”。 也许这样?
var data = new Dictionary<string, string>(); 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”文件可以通过假设“=”是分隔符来分割 – 但是格式比这更复杂,并允许在属性名称或值中embedded空格,等号,换行符和任何Unicode字符。
我需要为C#应用程序加载一些Java属性,所以我实现了JavaProperties.cs,使用与Java版本相同的方法正确读写“.properties”格式的文件 – 您可以在http://www.kajabity .com / index.php / 2009/06 / loading-java-properties-files-in-csharp / 。
在那里,你会发现一个包含这个类的C#源文件的压缩文件,以及我testing过的一些样本属性文件。
请享用!
最后一堂课。 谢谢@ eXXL 。
public class Properties { private Dictionary<String, String> list; 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<String, String>(); 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行,outcommenting和在文件中引用。
例子:
VAR1 = “VALUE1”
VAR2 = '值'
“VAR3 = outcommented
; var4 = outcommented
这里的方法是:
public static IDictionary ReadDictionaryFile(string fileName) { Dictionary<string, string> dictionary = new Dictionary<string, string>(); 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; }
是的,没有内build的课程可以做到这一点,我知道。
但是这不应该是一个问题吗? 通过将Stream.ReadToEnd()
的结果存储在一个string中,根据新行分割,然后将每个logging分成=
字符,看起来很容易parsing。 你会留下的是一堆关键的价值对,你可以很容易地折腾成一本字典。
以下是一个可能适用于您的示例:
public static Dictionary<string, string> GetProperties(string path) { string fileData = ""; using (StreamReader sr = new StreamReader(path)) { fileData = sr.ReadToEnd().Replace("\r", ""); } Dictionary<string, string> Properties = new Dictionary<string, string>(); string[] kvp; string[] records = fileData.Split("\n".ToCharArray()); foreach (string record in records) { kvp = record.Split("=".ToCharArray()); Properties.Add(kvp[0], kvp[1]); } return Properties; }
这是一个如何使用它的例子:
Dictionary<string,string> Properties = GetProperties("data.txt"); Console.WriteLine("Hello: " + Properties["Hello"]); Console.ReadKey();
C#通常使用基于xml的configuration文件,而不是像你所说的* .ini-style文件,所以没有内置来处理这个。 但是,谷歌返回了一些有希望的结果 。
我不知道有什么内置的方式来做到这一点。 但是,看起来似乎很容易,因为唯一需要担心的分隔符是换行符和等号。
编写一个返回NameValueCollection的例程或给定文件内容的IDictionary会非常容易。
您还可以使用默认值和限制集的C#自动属性语法。 这里的好处是你可以在你的属性“文件”(现在实际上是一个类)中拥有任何types的数据types。 另一个好处是你可以使用C#属性语法来调用属性。 但是,对于每个属性(属性声明中的一个和构造函数中的一个),只需要几行即可完成此工作。
using System; namespace ReportTester { class TestProperties { internal String ReportServerUrl { get; private set; } internal TestProperties() { ReportServerUrl = "http://myhost/ReportServer/ReportExecution2005.asmx?wsdl"; } } }
真正的答案是否定的(至less不是本身)。 你仍然可以编写你自己的代码来做到这一点。
我意识到,这不是你正在问的,但以防万一:
当你想加载一个真正的 Java属性文件时,你需要调整它的编码。 Java文档指出编码是ISO 8859-1,其中包含一些您可能无法正确解释的转义序列。 例如,看看这个答案 ,看看把UTF-8变成ISO 8859-1(反之亦然)
当我们需要这样做的时候,我们find了一个开源的PropertyFile.cs,并做了一些改动来支持转义序列。 这个类对于读/写场景是一个很好的select。 您还需要支持PropertyFileIterator.cs类。
即使你没有加载真正的Java属性,确保你的prop文件可以expression你需要保存的所有字符(至less是UTF-8)
有你想要的确切解决scheme。 请从这里find文章
他的代码在效率方面有很多优点。
- 应用程序不会在每个请求中加载文本文件。 它只将文本文件加载到内存一次。 对于后续的请求,它直接从内存中返回值。 如果您的文本文件包含数千个或更多的键值对,效率会更高。
- 文本文件中的任何更改都不需要重新启动应用程序。 已经使用文件系统观察器来跟踪文件状态。 如果它发生变化,它会触发一个事件,并相应地将新的更改加载到内存中,以便您可以在一个应用程序/文本编辑器中更改文本文件,并在Web应用程序中查看已更改的效果。
- 您不仅可以在Web应用程序中使用它,而且还可以在任何桌面应用程序中使用它。
谢谢。 祝你今天愉快。