1

ストリーム/リーダーをc#で行ごとにフィルタリングする最も簡単な方法は何ですか(パイプラインの途中にsedを配置するようなものです)。iCalendarファイルをDDay.iCalにフィードしたいのですが、DDay.iCalは「VERSION:5.1.1」で終了します。これは、数値または数値のセミコロン番号(数値は数字(DOT桁)ですか?最後の「。」は予期しない)。

私がやりたいのは、VERSION:行を「VERSION:5.1」のような無害なものにフィルタリングして、パーサーが死なないようにすることです。

更新:OK、ここにサンプルがあります:

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

さて、DDay.iCalパーサーは「VERSION:5.1.1」が好きではないので、「VERSION:5.1」のような無害なものに置き換えたいと思います。

パーサーインターフェイスは、リーダーまたはストリームを取ります。

とにかく、私はここでコードを使用しようとしましたが、それは機能します(フィルター処理されたReadLineの上にTextReaderを再実装します)。

4

2 に答える 2

8

System.IO.Stream はデコレーター パターンを使用するため、基になるストリームをラップする独自のパターンを簡単に作成できます。これにより、CryptoStream や GZipStream などのストリームは、他の Stream インスタンスをラップし、拡張するクラスから派生することなく、その読み取り/書き込みメソッドを効果的に「オーバーライド」できます。ギャング オブ フォーの本で説明されている非常に柔軟で人気のあるデザイン パターン。

使用している API に Stream または StreamReader が必要かどうかはわかりません。両者には大きな違いがあります。StreamReader はテキストレベルで機能し、文字/行を操作します。Stream はバイナリ レベルで動作し、バイトを操作します。つまり、StreamReader はバイトをテキストにデコードできるため、消費者はエンコーディングを気にする必要がありません。エンコードが問題にならない場合 (圧縮や暗号化の場合など) は Stream を使用し、テキスト データを操作する場合は StreamReader を使用します。

ここでは、StreamReader の方が理にかなっています。API が StreamReader を受け入れることができる場合は、TextReader から独自のものを派生させ、その ReadLine メソッドをオーバーライドして、追加する必要があるテキスト行が最初の呼び出しで返され、後続の呼び出しが通常どおり機能するようにします。

もう 1 つのオプションは、StringWriter/StringReader を使用して、すべてをメモリ内の文字列バッファーに詰め込み、操作してから渡すことです。

于 2009-06-15T03:33:39.447 に答える
5

最も簡単な方法は、ストリームをIEnumerableとしてラップし、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();
    }
}

上記のシーケンスは整数のみをフィルタリングしますが、必要なすべての入力を処理するためのより優れたフィルターを作成するのに十分簡単です。

于 2009-06-15T03:21:28.477 に答える