Puede .De carga NETA y analizar un archivo de propiedades equivalentes a las Propiedades de Java de la clase?

StackOverflow https://stackoverflow.com/questions/485659

Pregunta

¿Hay una manera fácil en C# para leer un archivo de propiedades que tiene cada propiedad en una línea separada seguido por un signo igual y el valor, tales como los siguientes:

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

En Java, las Propiedades de la clase se encarga de esto analizar fácilmente:

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

Fácilmente se puede cargar el archivo en C# y analizar cada línea, pero hay una construida en forma fácil de obtener una propiedad sin tener que analizar el nombre de la clave y el signo de igual a mí mismo?El C# información que he encontrado parece siempre a favor de XML, pero este es un archivo existente que no controlo, y prefiero mantenerlo en el formato existente, ya que se requieren más tiempo para conseguir otro equipo para cambiar a XML que analizar el archivo existente.

¿Fue útil?

Solución

No, no hay soporte integrado para esto.

Tienes que hacer tu propio " INIFileReader " ;. Tal vez algo como esto?

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

Editar: actualizado para reflejar el comentario de Paul.

Otros consejos

La mayoría de Java " .properties " los archivos se pueden dividir asumiendo que " = " es el separador, pero el formato es significativamente más complicado que eso y permite incrustar espacios, iguales, nuevas líneas y cualquier carácter Unicode en el nombre o valor de la propiedad.

Necesitaba cargar algunas propiedades Java para una aplicación C #, así que he implementado JavaProperties.cs para leer y escribir correctamente " .properties " archivos formateados con el mismo enfoque que la versión de Java: puede encontrarlo en http://www.kajabity.com/index.php/2009/06/loading-java-properties-files-in-csharp/ .

Allí, encontrará un archivo zip que contiene la fuente de C # para la clase y algunos archivos de propiedades de muestra con los que lo probé.

¡Disfruta!

Clase final. Gracias @ 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 { }
            }
        }
    }


}

Ejemplo de uso:

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

He escrito un método que permite líneas vacías, comentarios y citas dentro del archivo.

Ejemplos:

var1 = " valor1 "
var2 = 'value2'

'var3 = descomentado
; var4 = también comentado

Aquí está el método:

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

Otra respuesta (en enero de 2018) a la vieja pregunta (en enero de 2009).

La especificación de archivo de propiedades Java se describe en el JavaDoc de java.util.Propiedades.de carga(java.io.El lector).Uno de los problemas es que la especificación es un poco complicado que la primera impresión que podemos tener.Otro problema es que algunas respuestas aquí arbitrariamente adicional especificaciones - por ejemplo, ; y ' son considerados como titulares de las líneas de comentario, pero no debe ser.Doble/solo citas en torno a los valores de la propiedad se quitan, pero no debe ser.

Los siguientes son puntos a tener en cuenta.

  1. Hay dos tipos de línea, líneas naturales y las líneas lógicas.
  2. Una línea natural se termina por \n, \r, \r\n o el final de la secuencia.
  3. Una línea lógica puede ser extendido a través de varias adyacentes líneas naturales escapando el terminador de línea de secuencia con un carácter de barra diagonal inversa \.
  4. Los espacios en blanco al inicio de la segunda y siguientes líneas naturales en una línea lógica se descartan.
  5. Los espacios en blanco son el espacio (, \u0020), tab (\t, \u0009) y la forma de alimentación (\f, \u000C).
  6. Como se indica explícitamente en la especificación, "no es suficiente con sólo examinar el carácter que precede a un terminador de línea de secuencia para decidir si el terminador de línea se escapó;debe haber un número impar de barras contiguas para el terminador de línea para ser escapado.Desde la entrada se procesan de izquierda a derecha, un no-cero, incluso el número de 2n contiguos barras invertidas antes de un terminador de línea (o en otra parte) codifica n barras diagonales inversas después de escapar de procesamiento."
  7. = se utiliza como separador entre una clave y un valor.
  8. : se utiliza como separador entre una clave y un valor, también.
  9. El separador entre una clave y un valor puede ser omitido.
  10. Una línea de comentario se ha # o ! como su primer caracteres sin espacios en blanco, lo que significa que conducen los espacios en blanco antes # o ! están permitidos.
  11. Una línea de comentario no puede ser extendida a la siguiente naturales líneas, incluso su terminador de línea es precedido por \.
  12. Como se indica explícitamente en la especificación, =, : y espacios en blanco que puede ser incrustado en una clave si se escapan por barras diagonales inversas.
  13. Incluso terminador de línea de caracteres se puede incluir el uso de \r y \n las secuencias de escape.
  14. Si un valor se omite, una cadena vacía se utiliza como un valor.
  15. \uxxxx se utiliza para representar un carácter Unicode.
  16. Un carácter de barra diagonal inversa antes que un no-válido carácter de escape no es tratado como un error;es en silencio cayó.

Así, por ejemplo, si test.properties tiene el siguiente contenido:

# 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

debe ser interpretada como los siguientes pares clave-valor.

+------+--------------------+
| KEY  | VALUE              |
+------+--------------------+
| key1 | value1             |
| key2 | value2             |
| key3 | value3             |
| key4 | value4             |
| key5 | value5             |
| key6 | value6             |
| : =  | \colon\space\equal |
+------+--------------------+

PropertiesLoader clase en Authlete.Authlete Paquete de NuGet puede interpretar el formato de la especificación.El ejemplo de código siguiente:

using System;
using System.IO;
using System.Collections.Generic;
using Authlete.Util;

namespace MyApp
{
    class Program
    {
        public static void Main(string[] args)
        {
            string file = "test.properties";
            IDictionary<string, string> properties;

            using (TextReader reader = new StreamReader(file))
            {
                properties = PropertiesLoader.Load(reader);
            }

            foreach (var entry in properties)
            {
                Console.WriteLine($"{entry.Key} = {entry.Value}");
            }
        }
    }
}

generará la siguiente salida:

key1 = value1
key2 = value2
key3 = value3
key4 = value4
key5 = value5
key6 = value6
: = = \colon\space\equal

Un equivalente de ejemplo en Java es la siguiente:

import java.util.*;
import java.io.*;

public class Program
{
    public static void main(String[] args) throws IOException
    {
        String file = "test.properties";
        Properties properties = new Properties();

        try (Reader reader = new FileReader(file))
        {
             properties.load(reader);
        }

        for (Map.Entry<Object, Object> entry : properties.entrySet())
        {
            System.out.format("%s = %s\n", entry.getKey(), entry.getValue());
        }    
    }
}

El código fuente, PropertiesLoader.cs, se puede encontrar en authlete-csharp. xUnit pruebas para PropertiesLoader están escritos en PropertiesLoaderTest.cs.

Sí, no hay clases integradas para hacer esto que yo sepa.

Pero eso no debería ser realmente un problema, ¿verdad? Parece bastante fácil de analizar simplemente almacenando el resultado de Stream.ReadToEnd() en una cadena, dividiendo en base a nuevas líneas y luego dividiendo cada registro en el carácter =. Lo que te quedaría es un montón de pares de valores clave que puedes incluir fácilmente en un diccionario.

Aquí hay un ejemplo que podría funcionar para usted:

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

Aquí hay un ejemplo de cómo usarlo:

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

La respuesta real es no (al menos no por sí sola). Todavía puede escribir su propio código para hacerlo.

C# utiliza, por lo general basado en xml de los archivos de configuración en lugar de la *.ini-archivo de estilo como usted lo dijo, así que no hay nada construido para manejar esto.Sin embargo, google devuelve una número de resultados prometedores.

No conozco ninguna forma integrada de hacer esto. Sin embargo, parece bastante fácil de hacer, ya que los únicos delimitadores de los que debe preocuparse son el carácter de nueva línea y el signo igual.

Sería muy fácil escribir una rutina que devolverá una NameValueCollection, o un IDictionary dado el contenido del archivo.

También puede usar la sintaxis de propiedad automática de C # con valores predeterminados y un conjunto restrictivo. La ventaja aquí es que puede tener cualquier tipo de tipo de datos en sus propiedades & Quot; file & Quot; (ahora en realidad una clase). La otra ventaja es que puede usar la sintaxis de propiedad C # para invocar las propiedades. Sin embargo, solo necesita un par de líneas para cada propiedad (una en la declaración de propiedad y otra en el constructor) para que esto funcione.

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

Hay varios paquetes NuGet para esto, pero todos están actualmente en versión preliminar.

[Actualizar] A partir de junio de 2018, Capgemini.Cauldron.Core.JavaProperties es ahora en una versión estable (versión 2.1.0 y 3.0.20).

Me doy cuenta de que esto no es exactamente lo que estás preguntando, pero por si acaso:

Cuando desee cargar un archivo de propiedades Java real , deberá acomodar su codificación. Los documentos de Java indican que La codificación es ISO 8859-1, que contiene algunas secuencias de escape que quizás no interpretes correctamente. Por ejemplo, mire esta respuesta SO para ver qué hay necesario para convertir UTF-8 en ISO 8859-1 (y viceversa)

Cuando necesitábamos hacer esto, encontramos un código abierto PropertyFile.cs e hizo algunos cambios para admitir las secuencias de escape. Esta clase es buena para escenarios de lectura / escritura. También necesitará la PropertyFileIterator.cs clase de apoyo.

Incluso si no está cargando propiedades Java verdaderas, asegúrese de que su archivo de utilería pueda expresar todos los caracteres que necesita guardar (UTF-8 al menos)

Existe la solución exacta de lo que quieres. encuentre el artículo de aquí

su código tiene un montón de puntos fuertes con respecto a la eficiencia.

  1. La aplicación no carga el archivo de texto en cada solicitud. Eso carga el archivo de texto solo una vez en la memoria. Para el posterior solicitud, devuelve el valor directamente desde la memoria. Esto es mucho más eficiente si su archivo de texto contiene miles o más pares clave-valor.
  2. Cualquier cambio en el archivo de texto no requiere reiniciar la aplicación. UNA El observador del sistema de archivos se ha utilizado para realizar un seguimiento del estado del archivo. Si cambia, desencadena un evento y carga los nuevos cambios de acuerdo con la memoria para que pueda cambiar el archivo de texto en uno aplicación / editor de texto y ver el efecto cambiado en la web aplicación.
  3. No solo puede usarlo en una aplicación web sino que también puede para usarlo en cualquier aplicación de escritorio.

Gracias. Que tengas un buen día.

No, no lo hay: pero he creado una clase fácil para ayudar:

public class PropertiesUtility
{
    private static Hashtable ht = new Hashtable();
    public void loadProperties(string path)
    {
        string[] lines = System.IO.File.ReadAllLines(path);
        bool readFlag = false;
        foreach (string line in lines)
        {
            string text = Regex.Replace(line, @"\s+", "");
            readFlag =  checkSyntax(text);
            if (readFlag)
            {
                string[] splitText = text.Split('=');
                ht.Add(splitText[0].ToLower(), splitText[1]);
            }
        }
    }

    private bool checkSyntax(string line)
    {
        if (String.IsNullOrEmpty(line) || line[0].Equals('['))
        {
            return false;
        }

        if (line.Contains("=") && !String.IsNullOrEmpty(line.Split('=')[0]) && !String.IsNullOrEmpty(line.Split('=')[1]))
        {
            return true;
        }
        else
        {
            throw new Exception("Can not Parse Properties file please verify the syntax");
        }
    }

    public string getProperty(string key)
    {
        if (ht.Contains(key))
        {
            return ht[key].ToString();
        }
        else
        {
            throw new Exception("Property:" + key + "Does not exist");
        }

    }
}

Espero que esto ayude.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top