首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无缓冲StreamReader

无缓冲StreamReader
EN

Stack Overflow用户
提问于 2009-02-06 15:31:50
回答 2查看 5.1K关注 0票数 21

有没有办法阻止StreamReader做任何缓冲?

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

代码语言:javascript
复制
Content-type: application/whatever
Another-header: value

text or binary data here

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

代码语言:javascript
复制
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());
}

这似乎是对二进制数据的垃圾处理。因此,我将最后一行改为如下所示:

代码语言:javascript
复制
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所在的位置吗?

EN

回答 2

Stack Overflow用户

发布于 2010-03-23 08:30:17

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

我的问题涉及到PPM files,它具有类似的格式:

文件的其余部分以beginning

  • Binary字节表示的
  • ASCII文本

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

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

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

代码语言:javascript
复制
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();
    }
}
票数 9
EN

Stack Overflow用户

发布于 2009-02-06 17:21:05

您可以使用Stream.Seek来设置流的位置。在我看来,您在这里遇到的问题是StreamReader读取的是字符而不是字节(根据编码的不同,这可能不同于每个字符1个字节)。从MSDN Library

StreamStream类是为特定编码的字符输入而设计的,而

StreamReader类是为字节输入和输出而设计的。

当您调用reader.ReadToEnd()时,它根据所使用的编码将数据作为字符串读入。使用Stream.Read方法可能会更幸运。使用StreamReader读入字符串数据,然后在读入通知您传入二进制数据的头之后,将二进制数据提取到byte[]中。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/520722

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档