C# .NET 可以加载和解析与 Java Properties 类等效的属性文件吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/485659/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 05:16:50  来源:igfitidea点击:

Can .NET load and parse a properties file equivalent to Java Properties class?

c#configurationfile-ioload

提问by Tai Squared

Is there an easy way in C# to read a properties file that has each property on a separate line followed by an equals sign and the value, such as the following:

在 C# 中是否有一种简单的方法来读取属性文件,该文件在单独的行上具有每个属性,后跟等号和值,例如以下内容:

ServerName=prod-srv1
Port=8888
CustomProperty=Any value

In Java, the Properties class handles this parsing easily:

在 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"));

I can easily load the file in C# and parse each line, but is there a built in way to easily get a property without having to parse out the key name and equals sign myself? The C# information I have found seems to always favor XML, but this is an existing file that I don't control and I would prefer to keep it in the existing format as it will require more time to get another team to change it to XML than parsing the existing file.

我可以轻松地在 C# 中加载文件并解析每一行,但是是否有一种内置的方法可以轻松获取属性而无需自己解析键名和等号?我发现的 C# 信息似乎总是支持 XML,但这是一个我无法控制的现有文件,我更愿意将其保留为现有格式,因为它需要更多时间让另一个团队将其更改为 XML而不是解析现有文件。

采纳答案by Jesper Palm

No there is no built-in support for this.

不,没有对此的内置支持。

You have to make your own "INIFileReader". Maybe something like this?

您必须制作自己的“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"]);

Edit: Updated to reflect Paul's comment.

编辑:更新以反映保罗的评论。

回答by Joel Coehoorn

C# generally uses xml-based config files rather than the *.ini-style file like you said, so there's nothing built-in to handle this. However, google returns a number of promising results.

C# 通常使用基于 xml 的配置文件,而不是像你说的 *.ini 样式的文件,所以没有内置的东西来处理这个问题。然而,谷歌返回了许多有希望的结果

回答by casperOne

I don't know of any built-in way to do this. However, it would seem easy enough to do, since the only delimiters you have to worry about are the newline character and the equals sign.

我不知道有什么内置的方法可以做到这一点。但是,这似乎很容易做到,因为您唯一需要担心的分隔符是换行符和等号。

It would be very easy to write a routine that will return a NameValueCollection, or an IDictionary given the contents of the file.

编写一个例程将返回 NameValueCollection 或给定文件内容的 IDictionary 将非常容易。

回答by Spencer Ruport

Yeah there's no built in classes to do this that I'm aware of.

是的,我知道没有内置的类可以做到这一点。

But that shouldn't really be an issue should it? It looks easy enough to parse just by storing the result of Stream.ReadToEnd()in a string, splitting based on new lines and then splitting each record on the =character. What you'd be left with is a bunch of key value pairs which you can easily toss into a dictionary.

但这真的不应该是一个问题吧?只需将 的结果存储Stream.ReadToEnd()在字符串中,根据新行进行拆分,然后拆分=字符上的每个记录,就可以很容易地进行解析。剩下的是一堆键值对,您可以轻松地将它们放入字典中。

Here's an example that might work for you:

这是一个可能对您有用的示例:

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;
}

Here's an example of how to use it:

以下是如何使用它的示例:

Dictionary<string,string> Properties = GetProperties("data.txt");
Console.WriteLine("Hello: " + Properties["Hello"]);
Console.ReadKey();

回答by eXXL

I've written a method that allows emty lines, outcommenting and quoting within the file.

我编写了一个方法,允许在文件中使用空行、注释和引用。

Examples:

例子:

var1="value1"
var2='value2'

var1="value1"
var2='value2'

'var3=outcommented
;var4=outcommented, too

'var3=outcommented
;var4=outcommented,也是

Here's the method:

这是方法:

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;
}

回答by eXXL

Most Java ".properties" files can be split by assuming the "=" is the separator - but the format is significantly more complicated than that and allows for embedding spaces, equals, newlines and any Unicode characters in either the property name or value.

大多数Java“.properties”文件可以通过假设“=”是分隔符来分割——但格式比这复杂得多,并且允许在属性名称或值中嵌入空格、等号、换行符和任何Unicode字符。

I needed to load some Java properties for a C# application so I have implemented JavaProperties.cs to correctly read and write ".properties" formatted files using the same approach as the Java version - you can find it at http://www.kajabity.com/index.php/2009/06/loading-java-properties-files-in-csharp/.

我需要为 C# 应用程序加载一些 Java 属性,因此我实现了 JavaProperties.cs 以使用与 Java 版本相同的方法正确读取和写入“.properties”格式的文件 - 您可以在http://www.kajabity找到它.com/index.php/2009/06/loading-java-properties-files-in-csharp/

There, you will find a zip file containing the C# source for the class and some sample properties files I tested it with.

在那里,您会找到一个 zip 文件,其中包含该类的 C# 源代码以及我用来测试它的一些示例属性文件。

Enjoy!

享受!

回答by Steve Eisner

I realize that this isn't exactly what you're asking, but just in case:

我意识到这不完全是你要问的,但以防万一:

When you want to load an actualJava properties file, you'll need to accomodate its encoding. The Java docsindicate that the encoding is ISO 8859-1, which contains some escape sequences that you might not correctly interpret. For instance look at this SO answerto see what's necessary to turn UTF-8 into ISO 8859-1 (and vice versa)

当您想要加载实际的Java 属性文件时,您需要适应其编码。 Java 文档指出编码是 ISO 8859-1,其中包含一些您可能无法正确解释的转义序列。例如,查看这个 SO answer以了解将 UTF-8 转换为 ISO 8859-1 的必要条件(反之亦然)

When we needed to do this, we found an open-source PropertyFile.csand made a few changes to support the escape sequences. This class is a good one for read/write scenarios. You'll need the supporting PropertyFileIterator.csclass as well.

当我们需要这样做时,我们找到了一个开源的PropertyFile.cs并进行了一些更改以支持转义序列。这个类非常适合读/写场景。您还需要支持PropertyFileIterator.cs类。

Even if you're not loading true Java properties, make sure that your prop file can express all the characters you need to save (UTF-8 at least)

即使您没有加载真正的 Java 属性,也要确保您的 prop 文件可以表达您需要保存的所有字符(至少为 UTF-8)

回答by Jason Weden

You can also use C# automatic property syntax with default values and a restrictive set. The advantage here is that you can then have any kind of data type in your properties "file" (now actually a class). The other advantage is that you can use C# property syntax to invoke the properties. However, you just need a couple of lines for each property (one in the property declaration and one in the constructor) to make this work.

您还可以使用带有默认值和限制集的 C# 自动属性语法。这里的优点是您可以在属性“文件”(现在实际上是一个类)中拥有任何类型的数据类型。另一个优点是您可以使用 C# 属性语法来调用属性。但是,您只需要为每个属性添加几行(属性声明中的一行,构造函数中的一行)即可完成这项工作。

using System;
namespace ReportTester {
   class TestProperties
   {
        internal String ReportServerUrl { get; private set; }
        internal TestProperties()
        {
            ReportServerUrl = "http://myhost/ReportServer/ReportExecution2005.asmx?wsdl";
        }
   }
}

回答by Nick Rimmer

Final class. Thanks @eXXL.

最后一节课。谢谢@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 { }
            }
        }
    }


}

Sample use:

样品用途:

//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()

回答by Carl Thronson

The real answer is no (at least not by itself). You can still write your own code to do it.

真正的答案是否定的(至少本身不是)。您仍然可以编写自己的代码来执行此操作。