2008-08-17 11 views
9

quiero analizar una cosa sorta archivo de configuración, así:¿El mejor método de análisis de archivos de texto en C#?

[KEY:Value]  
    [SUBKEY:SubValue] 

Ahora me comenzó con una StreamReader, la conversión de las líneas en las matrices de caracteres, cuando me di cuenta tiene que haber una mejor manera. Entonces, te pido, humilde lector, que me ayudes.

Una restricción es que tiene que funcionar en un entorno Linux/Mono (1.2.6 para ser exactos). No tengo la última versión 2.0 (de Mono), así que trate de restringir las características del lenguaje a C# 2.0 o C# 1.0.

Respuesta

12

Lo consideré, pero no voy a usar XML. Voy a escribir esto a mano, y editar manualmente XML hace que me duela el cerebro. : ')

¿Has mirado YAML?

Obtiene los beneficios de XML sin todo el dolor y el sufrimiento. Se utiliza ampliamente en la comunidad de rubí para cosas como archivos de configuración, los datos de la base de datos previamente preparado, etc

He aquí un ejemplo

customer: 
    name: Orion 
    age: 26 
    addresses: 
    - type: Work 
     number: 12 
     street: Bob Street 
    - type: Home 
     number: 15 
     street: Secret Road 

Parece que hay un C# library here, que no he utilizado personalmente, pero yaml es bastante simple, así que "¿qué tan difícil puede ser?":-)

Yo diría que es preferible a inventar su propio formato ad-hoc (y hacer frente a los errores del analizador)

0

Me parece que sería mejor usar un archivo de configuración basado en XML, ya que ya hay clases .NET que pueden leer y almacenar la información para usted con relativa facilidad. ¿Hay alguna razón por la cual esto no es posible?

@Bernard: Es cierto que la edición manual de XML es tediosa, pero la estructura que usted presenta ya se ve muy similar a XML.

Entonces sí, tiene un buen método allí.

0

También puede usar una pila y usar un algoritmo push/pop. Éste coincide con las etiquetas de apertura/cierre.

public string check() 
    { 
     ArrayList tags = getTags(); 


     int stackSize = tags.Count; 

     Stack stack = new Stack(stackSize); 

     foreach (string tag in tags) 
     { 
      if (!tag.Contains('/')) 
      { 
       stack.push(tag); 
      } 
      else 
      { 
       if (!stack.isEmpty()) 
       { 
        string startTag = stack.pop(); 
        startTag = startTag.Substring(1, startTag.Length - 1); 
        string endTag = tag.Substring(2, tag.Length - 2); 
        if (!startTag.Equals(endTag)) 
        { 
         return "Fout: geen matchende eindtag"; 
        } 
       } 
       else 
       { 
        return "Fout: geen matchende openeningstag"; 
       } 
      } 
     } 

     if (!stack.isEmpty()) 
     { 
      return "Fout: geen matchende eindtag"; 
     }    
     return "Xml is valid"; 
    } 

Probablemente pueda adaptarse para que pueda leer el contenido de su archivo. Las expresiones regulares también son una buena idea.

4

Estaba viendo casi este problema el otro día: this article en tokenización de cadenas es exactamente lo que necesita. Usted querrá definir sus fichas como algo parecido a:

@"(?&ltlevel>\s) | " + 
@"(?&ltterm>[^:\s]) | " + 
@"(?&ltseparator>:)" 

El artículo hace un muy buen trabajo de explicarlo. A partir de ahí, simplemente comienzas a comer tokens como mejor te parezca.

Protip: Para un LL(1) parser (léase: fácil), los tokens no pueden compartir un prefijo. Si tiene abc como token, no puede tener ace como token

Nota: El artículo no se encuentra | caracteres en sus ejemplos, simplemente tírelos.

1

El uso de una biblioteca es casi siempre preferencia a rodar su propia cuenta. He aquí una lista rápida de "Oh nunca necesito que/yo no pienso que los" puntos que acabará llegando a morder después de la línea:.

  • caracteres Escapar ¿Qué pasa si usted quiere una: en la tecla o ] en el valor?
  • Escapar el carácter de escape
  • Unicode
  • Mezcla de fichas y espacios (ver los problemas con la sintaxis sensible espacio en blanco de Python)
  • Manejo de formatos de carácter diferente de retorno
  • manejo de errores de sintaxis informes

Al igual que otros han sugerido, YAML parece que su mejor apuesta.

-1

Independientemente del formato conservado, usar una Regex sería la forma más rápida de analizar. En ruby ​​probablemente serían unas pocas líneas de código.

\[KEY:(.*)\] 
\[SUBKEY:(.*)\] 

Estos dos obtendrán el Valor y SubValor en el primer grupo. Consulte MSDN sobre cómo hacer coincidir una expresión regular con una cadena.

Esto es algo que todos deberían tener en su gatito. Los días previos a Regex parecerían la Era de Hielo.

0

@Gishu

realidad una vez que lo alberga durante caracteres de escape mi expresión regular corrió ligeramente más lento que mi mano arriba anotado analizador recursivo y eso es sin la anidación (que une los subtemas a sus padres) y el informe de errores escrito a mano analizador tenía.

La expresión regular fue un poco más rápida de escribir (aunque tengo un poco de experiencia con analizadores de mano) pero eso es sin buenos informes de errores. Una vez que agrega que se vuelve un poco más difícil y más largo de hacer.

También encuentro el analizador escrito a mano más fácil de entender la intención de. Por ejemplo, aquí está el un fragmento de código:

private static Node ParseNode(TextReader reader) 
{ 
    Node node = new Node(); 
    int indentation = ParseWhitespace(reader); 
    Expect(reader, '['); 
    node.Key = ParseTerminatedString(reader, ':'); 
    node.Value = ParseTerminatedString(reader, ']'); 
} 
1

Hay another YAML library for .NET que está en fase de desarrollo. En este momento es compatible con la lectura de secuencias YAML y ha sido probado en Windows y Mono. El soporte de escritura se está implementando actualmente.