Domanda

Voglio analizzare una sorta di file di configurazione, in questo modo:

[KEY:Value]     
    [SUBKEY:SubValue]

Ora ho iniziato con a StreamReader, convertendo le linee in matrici di caratteri, quando ho pensato che ci dovesse essere un modo migliore.Quindi chiedo a te, umile lettore, di aiutarmi.

Una limitazione è che deve funzionare in un ambiente Linux/Mono (1.2.6 per l'esattezza).Non dispongo dell'ultima versione 2.0 (di Mono), quindi prova a limitare le funzionalità del linguaggio a C# 2.0 o C# 1.0.

È stato utile?

Soluzione

  

L'ho considerato, ma non userò XML. Scriverò queste cose a mano e l'editing manuale di XML mi fa male al cervello. : ')

Hai guardato YAML ?

Ottieni i vantaggi di XML senza tutto il dolore e la sofferenza. È ampiamente utilizzato nella comunità di ruby ??per cose come file di configurazione, dati di database pre-preparati, ecc.

ecco un esempio

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

Sembra che ci sia una libreria C # qui , che non ho usato personalmente, ma yaml è piuttosto semplice, quindi "quanto può essere difficile?" : -)

Direi che è preferibile inventare il proprio formato ad-hoc (e gestire i bug del parser)

Altri suggerimenti

L'altro giorno stavo esaminando quasi esattamente questo problema: questo articolo sul tokenizzazione delle stringhe è esattamente ciò di cui hai bisogno. Ti consigliamo di definire i tuoi token come qualcosa del tipo:

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

L'articolo fa un ottimo lavoro nel spiegarlo. Da lì inizi a mangiare token come ritieni opportuno.

Protip: per un LL (1) parser (leggi: facile), i token non possono condividere un prefisso. Se hai abc come token, non puoi avere ace come token

Nota: nell'articolo manca il | personaggi nei suoi esempi, inseriscili.

Esiste un'altra libreria YAML per .NET in fase di sviluppo. In questo momento supporta la lettura di flussi YAML ed è stato testato su Windows e Mono. Il supporto in scrittura è attualmente in fase di implementazione.

L'uso di una libreria è quasi sempre preferibilmente a rotazione. Ecco un breve elenco di " Oh, non ne avrò mai bisogno / Non ci ho pensato " punti che finiranno per venire a morderti più avanti lungo la linea:

  • Caratteri di escape. Cosa succede se si desidera un: nella chiave o] nel valore?
  • Scappa dal personaggio di fuga.
  • Unicode
  • Mix di schede e spazi (vedi i problemi con la sintassi sensibile agli spazi bianchi di Python)
  • Gestione di diversi formati di caratteri di ritorno
  • Gestione della segnalazione degli errori di sintassi

Come altri hanno suggerito, YAML sembra la soluzione migliore.

Puoi anche usare uno stack e usare un algoritmo push / pop. Questo corrisponde ai tag di apertura / chiusura.

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

Probabilmente puoi adattarti in modo da poter leggere il contenuto del tuo file. Anche le espressioni regolari sono una buona idea.

Mi sembra che sarebbe meglio usare un file di configurazione basato su XML poiché ci sono già classi .NET in grado di leggere e memorizzare le informazioni per te relativamente facilmente. C'è una ragione per cui ciò non è possibile?

@Bernard: È vero che l'editing manuale di XML è noioso, ma la struttura che stai presentando è già molto simile all'XML.

Quindi sì, ha un buon metodo lì.

@Gishu

In realtà una volta sistemato per i caratteri di escape, la mia regex è stata leggermente più lenta della mia mano scritta parser ricorsivo dall'alto verso il basso e questo è senza l'annidamento (che collega i sotto-elementi ai loro genitori) e l'errore che riportava il parser scritto a mano aveva.

Il regex è stato un po 'più veloce da scrivere (anche se ho un po' di esperienza con i parser manuali) ma questo è senza una buona segnalazione degli errori. Una volta aggiunto che diventa leggermente più difficile e più lungo da fare.

Trovo anche il parser scritto a mano più facile da capire l'intenzione di. Ad esempio, ecco uno snippet del codice:

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

Indipendentemente dal formato persistente, l'utilizzo di un Regex sarebbe il modo più veloce di analizzare. In ruby ??probabilmente ci sarebbero alcune righe di codice.

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

Questi due otterrebbero valore e valore secondario nel primo gruppo. Scopri MSDN su come abbinare una regex a una stringa.

Questo è qualcosa che tutti dovrebbero avere nel proprio gattino. I giorni pre-Regex sembrerebbero l'Era Glaciale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top