有没有办法让StreamReader不做任何缓冲?
我正在尝试处理可能是二进制或文本的进程的输出.输出看起来像HTTP响应,例如
Content-type: application/whatever Another-header: value text or binary data here
我想要做的是使用a解析标题StreamReader
,然后从其中读取BaseStream
或StreamReader
处理其余内容.这基本上是我开始的:
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. // i.e. 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() { Listbytes = 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(); } }