Подтвердить что ты не робот

Может ли .NET загружать и анализировать файл свойств, эквивалентный классу Java Properties?

Есть ли простой способ в С# прочитать файл свойств, который имеет каждое свойство в отдельной строке, за которым следует знак равенства и значение, например следующее:

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

Я могу легко загрузить файл на С# и проанализировать каждую строку, но есть ли встроенный способ легко получить свойство без необходимости разбирать имя ключа и знак равенства? Информация С#, которую я нашел, кажется, всегда благоприятствует XML, но это уже существующий файл, который я не контролирую, и я бы предпочел сохранить его в существующем формате, так как потребуется больше времени, чтобы заставить другую команду изменить его на XML чем анализ существующего файла.

4b9b3361

Ответ 1

Нет никакой встроенной поддержки для этого.

Вы должны создать свой собственный "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"]);

Изменить: Обновлено, чтобы отразить комментарий Павла.

Ответ 2

Большинство файлов Java.properties можно разделить, предположив, что "=" - это разделитель, - но формат значительно сложнее, чем этот, и позволяет встраивать пробелы, равенства, новые строки и любые символы Юникода либо в имя свойства или значение.

Мне нужно было загрузить некоторые свойства Java для приложения С#, поэтому я применил JavaProperties.cs для правильного чтения и записи форматированных файлов .properties с использованием того же подхода, что и версия Java, - вы можете найти его на http://www.kajabity.com/index.php/2009/06/loading-java-properties-files-in-csharp/.

Там вы найдете zip файл, содержащий источник С# для класса и некоторые файлы свойств образцов, с которыми я его тестировал.

Наслаждайтесь!

Ответ 3

Итоговый класс. Спасибо @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()

Ответ 4

Я написал метод, который позволяет создавать строки emty, outcommenting и quoting внутри файла.

Примеры:

var1 = "value1"
var2 = 'значение2'

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

Ответ 5

Да, нет никаких встроенных классов для этого, о которых я знаю.

Но это не должно быть проблемой, если это так? Это выглядит достаточно просто, чтобы анализировать, просто сохраняя результат Stream.ReadToEnd() в строке, разбивая на основе новых строк, а затем разбивая каждую запись на символ =. То, что вам останется, - это куча пар ключей, которые вы можете легко вставить в словарь.

Вот пример, который может сработать для вас:

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

Ответ 6

С# обычно использует конфигурационные файлы на основе xml, а не файл *.ini-типа, как вы сказали, поэтому нет ничего, чтобы справиться с этим. Однако google возвращает количество многообещающих результатов.

Ответ 7

Я не знаю никакого встроенного способа сделать это. Тем не менее, это было бы достаточно легко сделать, так как единственными разделителями, о которых вы должны беспокоиться, являются символ новой строки и знак равенства.

Было бы очень легко написать процедуру, которая вернет NameValueCollection или IDictionary, учитывая содержимое файла.

Ответ 8

Вы также можете использовать синтаксис автоматического синтаксиса С# со значениями по умолчанию и ограничительным набором. Преимущество здесь в том, что тогда у вас может быть тип данных любого типа в вашем файле "файл" (теперь на самом деле класс). Другое преимущество заключается в том, что вы можете использовать синтаксис свойств С# для вызова свойств. Тем не менее, вам просто нужно пару строк для каждого свойства (одно в объявлении свойства и одно в конструкторе), чтобы сделать эту работу.

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

Ответ 9

Реальный ответ - нет (по крайней мере, не сам по себе). Вы можете написать свой собственный код, чтобы сделать это.

Ответ 10

Я понимаю, что это не совсем то, что вы просите, но на всякий случай:

Если вы хотите загрузить фактический файл свойств Java, вам необходимо будет его кодировать. Документы Java показывают, что кодировка - это ISO 8859-1, которая содержит некоторые escape-последовательности, которые вы можете неправильно интерпретировать. Например, посмотрите этот ответ SO, чтобы узнать, что необходимо для превращения UTF-8 в ISO 8859-1 (и наоборот)

Когда нам нужно было это сделать, мы обнаружили open-source PropertyFile.cs и внесли несколько изменений для поддержки escape-последовательностей. Этот класс является хорошим для сценариев чтения/записи. Вам понадобится класс PropertyFileIterator.cs.

Даже если вы не загружаете истинные свойства Java, убедитесь, что ваш файл prop может выразить все символы, которые вам нужно сохранить (по крайней мере, UTF-8)

Ответ 11

Существует точное решение того, что вы хотите. пожалуйста, найдите статью здесь

у его кода есть куча сильных сторон относительно эффективности.

  • Приложение не загружает текстовый файл в каждом запросе. Это загружает текстовый файл только один раз в память. Для последующего request, он возвращает значение непосредственно из памяти. Это много более эффективен, если ваш текстовый файл содержит тысячи и более пары ключ-значение.
  • Любое изменение текстового файла не требует перезапуска приложения. Наблюдатель файловой системы использовался для отслеживания состояния файла. Если он изменяется, он запускает событие и загружает новые изменения соответственно памяти, чтобы вы могли изменить текстовый файл в одном приложение/текстовый редактор и увидеть измененный эффект в Интернете приложение.
  • Вы можете не только использовать его в веб-приложении, но и использовать его в любом настольном приложении.

Спасибо. Приятного дня.