【问题标题】:StreamReader Read method doesn't read number of chars specifiedStreamReader Read 方法不读取指定的字符数
【发布时间】:2012-07-03 03:13:55
【问题描述】:

我必须解析一个大文件,而不是这样做:

 string unparsedFile = myStreamReader.ReadToEnd(); // takes 4 seconds
 parse(unparsedFile); // takes another 4 seconds

我想利用前 4 秒的时间,尝试通过以下方式同时做这两件事:

        while (true)
        {
            char[] buffer = new char[1024];

            var charsRead = sr.Read(buffer, 0, buffer.Length);

            if (charsRead < 1)
                break;

            if (charsRead != 1024)
            {
                Console.Write("Here");  // debuger stops here several times why?
            }

            addChunkToQueue(buffer); 
        }

这是调试器的图像:(我添加了int counter 以显示我们读取的小于 1024 字节的迭代)

请注意,那里读取 643 个字符而不是 1024 个字符。在下一次迭代中,我得到:

我认为我应该一直读取 1024 字节,直到我到达最后一次迭代,其中剩余字节小于 1024。

所以我的问题是为什么我会在迭代抛出 while 循环时读取“随机”数量的字符?


编辑

我不知道我正在处理什么样的流。我执行如下流程:

        ProcessStartInfo psi = new ProcessStartInfo("someExe.exe")
        {
            RedirectStandardError = true,
            RedirectStandardOutput = true,
            UseShellExecute = false,
            CreateNoWindow = true,
        };

        // execute command and return ouput of command
        using (var proc = new Process())
        {
            proc.StartInfo = psi;
            proc.Start();                               

            var output = proc.StandardOutput;  //  <------------- this is where I get the strem

            //if (string.IsNullOrEmpty(output))
            //output = proc.StandardError.ReadToEnd();

            return output;
        }
    }

【问题讨论】:

  • 假设它总是被填充是一个糟糕的设计决策。如果它可能不会被填充,那么假设它不会,并相应地编码。

标签: c# streamreader


【解决方案1】:

一方面,您阅读的是字符,而不是字节。差别很大。

至于为什么它不一定会一次读取所有内容:也许没有那么多可用数据,StreamReader 决定给你它所拥有的,而不是阻塞一段不确定的时间来填充你的缓冲区。它完全有权这样做。

这是来自本地文件还是来自网络?通常,本地文件操作比网络下载更有可能填充缓冲区,但无论哪种方式,您都不应该依赖被填充的缓冲区。如果它是一个“文件”(即使用FileStream 读取),但它恰好位于网络共享上......好吧,据我所知,这是一个灰色区域:)它是一个流 - 就这样对待它。

【讨论】:

    【解决方案2】:

    这取决于您正在阅读的实际流。如果这是文件流,我想它不太可能获得“部分”数据。但是,如果您从网络流中读取数据,则必须期望数据以不同长度的块的形式出现。

    【讨论】:

      【解决方案3】:

      来自文档:http://msdn.microsoft.com/en-us/library/9kstw824

      当使用 Read 方法时,使用缓冲区更有效 与流的内部缓冲区大小相同,其中 内部缓冲区设置为您想要的块大小,并始终读取 小于块大小。如果内部缓冲区的大小是 构造流时未指定,其默认大小为 4 千字节(4096 字节)。如果你操纵的位置 将数据读入缓冲区后,底层流的位置 底层流可能与内部流的位置不匹配 缓冲。要重置内部缓冲区,请调用 DiscardBufferedData 方法;但是,此方法会降低性能,应调用 仅在绝对必要时。

      所以对于返回值,文档说:

      已读取的字符数,如果在末尾则为 0 > 流且未读取任何数据。该数字将小于或等于 到count参数,取决于数据是否可用 在信息流中。

      或者,总而言之 - 您的缓冲区和底层缓冲区的大小不同,因此您的缓冲区会被部分填充,因为底层缓冲区尚未被填满。

      【讨论】:

      • 如何获取流的内部缓冲区?它不是文件流也不是网络流。我很快就会在编辑中放置它是什么类型的流...
      • 我不确定您是否需要搜索此内容。流的当前行为是绝对正常的。您想获得更好的性能还是其他?内部缓冲区正在从网络中填充,因此如果您在那里遇到任何延迟 - 这是网络延迟,与缓冲区大小没有任何共同之处。缓冲区到缓冲区的复制是在内存中进行的。无论您做什么来同步缓冲区大小 - 这样做的性能优势对于网络延迟来说都是微不足道的。
      猜你喜欢
      • 2013-07-06
      • 2013-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-25
      • 2019-01-13
      • 2012-01-19
      • 1970-01-01
      相关资源
      最近更新 更多