2008-08-17 10 views
9

Je veux analyser une chose fichier de configuration de sorta, comme ceci:Meilleure méthode d'analyse de fichiers texte en C#?

[KEY:Value]  
    [SUBKEY:SubValue] 

Maintenant, j'ai commencé avec un StreamReader, la conversion des lignes dans des tableaux de caractères, quand je me suis dit, il doit y avoir une meilleure façon. Je vous demande donc, humble lecteur, de m'aider. Une restriction est qu'elle doit fonctionner dans un environnement Linux/Mono (1.2.6 pour être exact). Je n'ai pas la dernière version 2.0 (de Mono), alors essayez de restreindre les fonctionnalités de langage à C# 2.0 ou C# 1.0.

Répondre

12

Je l'ai considéré, mais je ne vais pas utiliser XML. Je vais écrire ces trucs à la main, et l'édition manuelle XML me fait mal au cerveau. : ')

Avez-vous regardé YAML?

Vous bénéficiez des avantages de XML sans la douleur et la souffrance. Il est largement utilisé dans la communauté Ruby pour des choses comme les fichiers de configuration, les données de base de données pré-préparés, etc

est ici un exemple

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

Il semble y avoir un C# library here, que je ne l'ai pas utilisé personnellement, mais yaml est assez simple, alors "comment peut-il être difficile?":-)

Je dirais qu'il est préférable d'inventer votre propre format ad hoc (et le traitement des bogues de l'analyseur)

0

Il me semble que vous feriez mieux d'utiliser un fichier de configuration basé sur XML car il existe déjà des classes .NET qui peuvent lire et stocker les informations pour vous relativement facilement. Y a-t-il une raison pour que ce ne soit pas possible? Il est vrai que l'édition manuelle de XML est fastidieuse, mais la structure que vous présentez ressemble déjà beaucoup à XML.

Alors oui, a une bonne méthode là.

0

Vous pouvez également utiliser une pile et utiliser un algorithme push/pop. Celui-ci correspond aux tags ouverts/fermants.

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

Vous pouvez probablement adapter afin que vous puissiez lire le contenu de votre fichier. Les expressions régulières sont également une bonne idée.

4

Je regardais presque ce problème exact l'autre jour: this article sur tokenisation de chaîne est exactement ce dont vous avez besoin. Vous aurez besoin de définir vos jetons comme quelque chose comme:

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

L'article fait un assez bon travail de l'expliquer. De là, vous commencez à manger des jetons comme bon vous semble.

Protip: Pour un LL(1) parser (lire: facile), les jetons ne peuvent pas partager un préfixe. Si vous avez abc en tant que marque, vous ne pouvez pas avoir ace en tant que marque

Note: Il manque l'article | caractères dans ses exemples, il suffit de les jeter.

1

En utilisant une bibliothèque est presque toujours de préférence à rouler votre propre. Voici une liste rapide des « Oh, je ne serai jamais besoin que/je ne pensais pas que des » points qui vont finir par venir à vous mordre plus tard la ligne.

  • caractères Échapper si vous voulez un: dans la clé ou ] dans la valeur?
  • Echappement du caractère d'échappement
  • Unicode
  • Mix des onglets et des espaces (voir les problèmes avec la syntaxe sensible à l'espace blanc de Python)
  • Gestion des différents formats de caractères de retour
  • Gestion des erreurs de syntaxe rapports

Comme d'autres l'ont suggéré, YAML ressemble à votre meilleur pari.

-1

Indépendamment du format persistant, l'utilisation d'un Regex serait le moyen le plus rapide d'analyser. Dans ruby ​​ce serait probablement quelques lignes de code.

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

Ces deux vous obtiendraient la valeur et SubValue dans le premier groupe. Découvrez MSDN sur la façon de faire correspondre une regex avec une chaîne.

C'est quelque chose que tout le monde devrait avoir dans son chat. Les jours pré-Regex sembleraient comme l'âge de glace.

0

@Gishu

En fait, une fois que je l'avais logé pour les personnages évadés mon regex ont légèrement plus lent que mon top écrit à la main vers le bas analyseur récursif et c'est sans l'imbrication (reliant les sous-éléments à leurs parents) et l'erreur de déclaration du manuscrit écrit à la main avait. L'expression régulière a été légèrement plus rapide à écrire (bien que j'ai un peu d'expérience avec les parseurs à main), mais c'est sans bonne déclaration d'erreur. Une fois que vous ajoutez que cela devient un peu plus difficile et plus long à faire.

Je trouve également l'analyseur écrit à la main plus facile à comprendre l'intention de. Par exemple, voici l'un extrait du code:

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

Il y a another YAML library for .NET qui est en cours de développement. À l'heure actuelle, il prend en charge la lecture des flux YAML et a été testé sur Windows et Mono. Le support en écriture est en cours de mise en œuvre.

Questions connexes