在c#中过滤流

时间:2009-06-15 03:11:35

标签: c# stream icalendar

在c#中逐行过滤流/阅读器的最简单方法是什么(有点像将sed放在管道中间)。我想将iCalendar文件提供给DDay.iCal,但DDay.iCal在“VERSION:5.1.1”上死亡,因为它需要一个数字或数字SEMICOLON编号(其中数字是数字(DOT数字)?所以最后一个“。”是意外)。

我想要做的是将VERSION:行过滤为像“VERSION:5.1”这样无害的东西,这样解析器就不会死了。

更新: 好的,这是一个样本:

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”之类的无害替换它。

解析器接口需要读取器或流。

无论如何,我尝试使用代码here并且它可以工作(在过滤的ReadLine之上重新实现TextReader)。

2 个答案:

答案 0 :(得分:7)

System.IO.Stream使用装饰器模式,因此可以很容易地创建自己的包装底层流。这允许诸如CryptoStream和GZipStream之类的流包装任何其他Stream实例并有效地“覆盖”其读/写方法,而不从您想要扩展的类派生。 “四人帮”一书中描述的非常灵活和流行的设计模式。

现在我不确定您使用的API是否需要Stream或StreamReader。两者之间存在显着差异。 StreamReader在 text 级别工作,对字符/行进行操作。 Stream工作在二进制级别并按字节操作。换句话说,期望StreamReader能够将字节解码为文本,以便消费者不需要关心编码。在编码无关紧要时(例如压缩或加密时)使用Stream,并在处理文本数据时使用StreamReader。

听起来,StreamReader在这里会更有意义。如果API可以接受StreamReader,只需从TextReader派生自己的并重写其ReadLine方法,以便第一个调用返回您需要附加的文本行,后续调用只是正常运行。

另一种选择是使用StringWriter / StringReader并将其全部填充到内存中的字符串缓冲区中,对其进行操作,然后传递它。

答案 1 :(得分: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();
    }
}

上面的序列只过滤整数,但它很容易编写一个更好的过滤器来处理你想要的所有输入。