问题描述
有没有办法让 StreamReader 不做任何缓冲?
Is there a way to keep StreamReader from doing any buffering?
我正在尝试处理来自可能是二进制或文本的进程的输出.输出看起来像一个 HTTP 响应,例如
I'm trying to handle output from a Process that may be either binary or text. The output will look like an HTTP Response, e.g.
Content-type: application/whatever
Another-header: value
text or binary data here
我想要做的是使用 StreamReader
解析标头,然后从它的 BaseStream
或 StreamReader
读取来处理其余的内容.这基本上是我开始的内容:
What I want to do is to parse the headers using a StreamReader
, and then either read from its BaseStream
or the StreamReader
to handle the rest of the content. Here's basically what I started with:
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());
}
这似乎会破坏二进制数据.所以我把最后一行改成了这样:
This seems to trash binary data. So I changed the last line to something like this:
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 所在的位置吗?
... but StreamReader buffers its input, so reader.BaseStream is in the wrong position. Is there a way to unbuffer StreamReader? Or can I tell StreamReader to reset the stream back to where StreamReader is?
推荐答案
这个答案来晚了,可能与您不再相关,但对于偶然发现此问题的其他人来说可能会派上用场.
This answer is late and possibly no longer relevant to you but it may come in handy for someone else who stumbles across this problem.
我的问题涉及PPM 文件,其格式类似:
My problem involved PPM files, which have a similar format of:
- 开头的 ASCII 文本
- 文件其余部分的二进制字节
我遇到的问题是 StreamReader
类无法在不缓冲内容的情况下一次读取一个字节.这在某些情况下会导致意外结果,因为 Read()
方法读取的是单个字符,而不是单个字节.
The problem I ran into was that the StreamReader
class is incapable of reading stuff one byte at a time without buffering stuff. This caused unexpected results in some cases, since the Read()
method reads a single character, not a single byte.
我的解决方案是围绕一个一次读取一个字节的流编写一个包装器.包装器有两个重要的方法,ReadLine()
和 Read()
.
My solution was to write a wrapper around a stream that would read bytes one at a time. The wrapper has 2 important methods, ReadLine()
and Read()
.
这 2 种方法允许我读取流的 ASCII 行,无缓冲,然后一次读取流的其余部分的一个字节.您可能需要进行一些调整以满足您的需要.
These 2 methods allow me to read the ASCII lines of a stream, unbuffered, and then read a single byte at a time for the rest of the stream. You may need to make some adjustments to suit your needs.
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
or some other
// convention that isn't just
public override string ReadLine()
{
List<byte> bytes = new List<byte>();
int current;
while ((current = Read()) != -1 && current != (int)'
')
{
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();
}
}
这篇关于无缓冲的 StreamReader的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!