Domanda

Qual è il modo più semplice per filtrare un flusso/lettore riga per linea in C# (un po 'come mettere SED al centro di una pipeline). Voglio alimentare un file ICALENDAR a DDay.ical ma Dday.ical Dies in "Versione: 5.1.1" perché vuole un numero o un numero di semili (dove il numero è cifre (cifre dot)? Quindi l'ultima ". inaspettato).

Quello che voglio fare è filtrare la versione: riga a qualcosa di innocuo come "Versione: 5.1" in modo che il parser non muoia.

AGGIORNAMENTO: OK, ecco un esempio:

BEGIN:VCALENDAR
PRODID:-//SunONE/Calendar Hosting Server//EN
METHOD:PUBLISH
VERSION:5.1.1
X-NSCP-CALPROPS-LAST-MODIFIED:20011208T005613Z
X-NSCP-CALPROPS-CREATED:20010913T223336Z
X-NSCP-CALPROPS-READ:999
X-NSCP-CALPROPS-WRITE:999

Ora, il parser Dday.ical non piace "Versione: 5.1.1", quindi voglio sostituirlo con qualcosa di innocuo come "Versione: 5.1".

L'interfaccia parser prende un lettore o un flusso.

Comunque, ho provato a usare il codice qui e funziona (reimplementazione di Textreader in cima a una readline filtrata).

È stato utile?

Soluzione

System.io.stream utilizza il motivo del decoratore in modo che sia abbastanza facile crearne uno che avvolge un flusso sottostante. Ciò consente a flussi come Cryptostream e Gzipstream di avvolgere qualsiasi altra istanza del flusso e "di sopravvivere" i suoi metodi di lettura/scrittura senza derivare dalla classe che si desidera estendere. Modello di design molto flessibile e popolare descritto nella banda di quattro libri.

Ora non sono sicuro che l'API con cui stai lavorando richieda un flusso o un flusso. C'è una distinzione significativa tra i due. Un flusso di flusso funziona al testo Livello e operazioni su caratteri/linee. Un flusso funziona a livello binario e opera su byte. In altre parole, si prevede che il REAder Stream sia in grado di decodificare i byte nel testo in modo che il consumatore non debba preoccuparsi della codifica. Utilizzare un flusso quando la codifica non ha importanza (ad esempio quando si comprime o entusiasmo) e usa un READER Stream quando si lavora con i dati di testo.

Da quello che sembra, un READER Stream avrebbe più senso qui. Se l'API può accettare un READER, basta derivare il proprio da Textreader e sovrascrivere il suo metodo di lettura in modo che la prima chiamata restituisca la riga di testo necessaria e le chiamate successive funzionino solo come normali.

L'altra opzione è quella di utilizzare solo un stringwriter/stringreder e riempi tutto in un buffer di stringa in memoria, manipolalo, quindi passalo.

Altri suggerimenti

Il modo più semplice potrebbe essere quello di avvolgere il flusso come un ignibo e filtrare con Linq:

static void Main(string[] args)
{
    System.IO.StreamReader sr = // ...
    var filtered = Enumerable.Where(
        StreamReaderToSeq(sr), input => { int temp; return int.TryParse(x, out temp); });
}

static IEnumerable<string> StreamReaderToSeq(System.IO.StreamReader sr)
{
    while(!sr.EndOfStream)
    {
        yield return sr.ReadLine();
    }
}

La sequenza sopra filtri solo numeri interi, ma è abbastanza facile scrivere un filtro migliore per gestire tutti gli ingressi desiderati.

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