有没有办法让StreamReader不做任何缓冲?
我正在尝试处理可能是二进制或文本的进程的输出.输出看起来像HTTP响应,例如
Content-type: application/whatever
Another-header: value
text or binary data here
Run Code Online (Sandbox Code Playgroud)
我想要做的是使用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());
}
Run Code Online (Sandbox Code Playgroud)
这似乎是垃圾二进制数据.所以我把最后一行改成了这样的东西:
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());
}
Run Code Online (Sandbox Code Playgroud)
...但是StreamReader缓冲了它的输入,因此reader.BaseStream处于错误的位置.有没有办法解密StreamReader?或者我可以告诉StreamReader将流重置回StreamReader所在的位置吗?
这个答案很晚,可能不再与你相关,但对于遇到这个问题的其他人来说,它可能会派上用场.
我的问题涉及PPM文件,其格式类似于:
我遇到的问题是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<byte> bytes = new List<byte>();
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();
}
}
Run Code Online (Sandbox Code Playgroud)
那么,您可以使用Stream.Seek来设置流的位置。在我看来,您遇到的问题是 StreamReader 正在读取字符而不是字节(根据编码的不同,字节可能与每个字符 1 个字节不同)。来自MSDN 库:
StreamReader 是为特定编码的字符输入而设计的,而 Stream 类是为字节输入和输出而设计的。
当您调用 reader.ReadToEnd() 时,它会根据所使用的编码将数据作为字符串读取。使用Stream.Read方法可能会有更好的运气。使用 StreamReader 读入字符串数据,然后在读入通知您传入二进制数据的标头后,将二进制数据提取到 byte[] 中。
| 归档时间: |
|
| 查看次数: |
4451 次 |
| 最近记录: |