无缓冲的StreamReader

有没有办法让StreamReader不做任何缓冲?

我正在尝试处理可能是二进制或文本的进程的输出。 输出看起来像HTTP响应,例如

Content-type: application/whatever Another-header: value text or binary data here 

我想要做的是使用StreamReader解析标头,然后从其BaseStreamStreamReader读取以处理其余内容。 这基本上就是我的开始:

 private static readonly Regex HttpHeader = new Regex("([^:]+): *(.*)"); private void HandleOutput(StreamReader reader) { var headers = new NameValueCollection(); string line; while((line = reader.ReadLine()) != null) { Match header = HttpHeader.Match(line); if(header.Success) { headers.Add(header.Groups[1].Value, header.Groups[2].Value); } else { break; } } DoStuff(reader.ReadToEnd()); } 

这似乎是垃圾二进制数据。 所以我把最后一行改成了这样的东西:

 if(headers["Content-type"] != "text/html") { // reader.BaseStream.Position is not at the same place that reader // makes it looks like it is. // ie reader.Read() != reader.BaseStream.Read() DoBinaryStuff(reader.BaseStream); } else { DoTextStuff(reader.ReadToEnd()); } 

…但是StreamReader缓冲了它的输入,因此reader.BaseStream处于错误的位置。 有没有办法取消缓冲StreamReader? 或者我可以告诉StreamReader将流重置回StreamReader所在的位置吗?

这个答案很晚,可能不再与你相关,但对于遇到这个问题的其他人来说,它可能会派上用场。

我的问题涉及PPM文件 ,其格式类似于:

  • 开头的ASCII文本
  • 文件其余部分的二进制字节

我遇到的问题是StreamReader类无法一次读取一个字节而没有缓冲内容。 这在某些情况下会导致意外结果,因为Read()方法读取单个字符,而不是单个字节。

我的解决方案是在流中编写一个包装器,一次读取一个字节。 包装器有两个重要的方法, ReadLine()Read()

这两种方法允许我读取流的ASCII行,无缓冲,然后一次读取一个字节用于流的其余部分。 您可能需要进行一些调整以满足您的需求。

 class UnbufferedStreamReader: TextReader { Stream s; public UnbufferedStreamReader(string path) { s = new FileStream(path, FileMode.Open); } public UnbufferedStreamReader(Stream stream) { s = stream; } // This method assumes lines end with a line feed. // You may need to modify this method if your stream // follows the Windows convention of \r\n or some other // convention that isn't just \n public override string ReadLine() { List bytes = new List(); int current; while ((current = Read()) != -1 && current != (int)'\n') { byte b = (byte)current; bytes.Add(b); } return Encoding.ASCII.GetString(bytes.ToArray()); } // Read works differently than the `Read()` method of a // TextReader. It reads the next BYTE rather than the next character public override int Read() { return s.ReadByte(); } public override void Close() { s.Close(); } protected override void Dispose(bool disposing) { s.Dispose(); } public override int Peek() { throw new NotImplementedException(); } public override int Read(char[] buffer, int index, int count) { throw new NotImplementedException(); } public override int ReadBlock(char[] buffer, int index, int count) { throw new NotImplementedException(); } public override string ReadToEnd() { throw new NotImplementedException(); } } 

好吧,您可以使用Stream.Seek来设置流的位置。 听起来像你在这里遇到的问题是StreamReader正在读取字符而不是字节(取决于编码,每个字符可能不同于1个字节)。 从MSDN Library :

StreamReader设计用于特定编码的字符输入,而Stream类设计用于字节输入和输出。

当你调用reader.ReadToEnd()时,它会根据它使用的任何编码将数据作为字符串读取。 使用Stream.Read方法可能会有更好的运气。 使用StreamReader读入字符串数据,然后在读入标题时将二进制数据拉出到byte []中,通知您输入的二进制数据。