【问题标题】:Limiting the size of data being read from a CSV file so it reads only full lines限制从 CSV 文件中读取的数据大小,使其仅读取整行
【发布时间】:2014-01-11 22:38:46
【问题描述】:

我想使用 C# 读取大约 10GB 的 CSV 文件。我无法一次读取一行文件,并且一次读取的最大块限制为 32MB。

如何限制我正在阅读的数据的大小,但同时确保我只阅读完整的行?这意味着如果一个完整的 32MB 意味着仅读取 100.5 行,那么我只想读取完整的 100 行并省略半行,即使这意味着读取小于 32MB。

这是我正在考虑的骨架代码(那里的cmets持有更多问题):

const int MAX_BUFFER = 33554432; //32MB
        byte[] buffer = new byte[MAX_BUFFER];
        int bytesRead;
        using (System.IO.FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            while ((bytesRead = fileStream.Read(buffer, 0, MAX_BUFFER)) != 0)
            {
                //should I somehow analyze here if what I'm reading containing only full lines? 
                //and if so, how can I know that I'm not currently reading something less than 32MB 
                //meaning bytesRead is less than that and that maybe I'm going to read the rest of the line in the next iteration?
            }

【问题讨论】:

  • File.EnumerateLines 能解决你的问题吗?
  • @usr 你写的好像不存在...
  • 似乎被称为“ReadLines”。 msdn.microsoft.com/en-us/library/dd383503(v=vs.110).aspx 那怎么样?
  • @Steve 但我怎么知道我在块末尾读到的不是整行?您似乎认为我总是在块的末尾读到一行
  • @Yonatan - 我已经将我所有的 cmets 移到了答案中。如果这对您有用,请接受它。不过,您可能需要等待更多输入。

标签: c# csv filestream


【解决方案1】:

您无需确保阅读的是完整的行。

将文件分块读取到缓冲区中。

逐个字符处理缓冲区中的每一行,直到到达换行符。如果您在一行中并到达缓冲区的末尾,请保留该部分,读取下一个块,并将从新读取到换行的所有内容与前一次读取的剩余部分连接起来。

如果缓冲区的最后一个字节是换行符,则您有整行并且可以简单地移动到下一个块。如果没有,请读取下一个块 - 第一个字节将是一个换行符,或者您将在它之前有其他字符。无论哪种方式,将所有内容连接到换行符(即使这意味着 0 个字符)并从下一个开始。

如果你在换行符之后点击文件末尾,你就完成了。如果您在处理非换行符时遇到文件末尾,则由您决定是将它们保留为有效行还是丢弃它们。

这与circular buffer 非常相似。

另一种解决方案可能是使用BufferedStream 并指定缓冲区大小。然后逐字节读取每个换行符或 EOF。

【讨论】:

  • +1,这似乎是要走的路。您可能还想确保您只查找 CSV 文件中可能存在的引用字符串外部的换行符。
  • 不,抱歉,我现在没有时间写一篇。
猜你喜欢
  • 1970-01-01
  • 2018-01-31
  • 2018-08-23
  • 2015-07-07
  • 2014-01-07
  • 2019-09-17
  • 1970-01-01
相关资源
最近更新 更多