3

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

 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;
        }
    }
4

3 回答 3

4

一方面,您正在阅读characters,而不是bytes。有很大的不同。

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

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

于 2012-07-02T18:58:05.700 回答
3

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

于 2012-07-02T18:58:41.983 回答
2

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

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

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

已读取的字符数,如果在 > 流的末尾并且没有读取数据,则为 0。该数字将小于或等于 count 参数,具体取决于数据在流中是否可用。

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

于 2012-07-02T18:59:21.173 回答