Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C:读取巨大的CSV文件_C#_Csv - Fatal编程技术网

C# C:读取巨大的CSV文件

C# C:读取巨大的CSV文件,c#,csv,C#,Csv,我正在解析一个40MB的CSV文件 它现在工作得很好,而且很容易解析,我唯一的问题是性能,这当然是相当慢的 我想知道是否有一种方法可以改进这一点,因为我只需要按键查找,然后停止循环,因此,如果条目位于文件的开头,它会很快完成,但如果位于结尾,则需要一段时间 我可以通过给它一个随机的起始线来平衡这一点,但算法仍然是在。。。所以我不确定这是否真的值得 有什么方法可以改进我的顺序解析算法吗?为什么不将csv转换为普通数据库呢。甚至sqlexpress也可以。当然可以 假设你按字母顺序排列。 然后,从中

我正在解析一个40MB的CSV文件

它现在工作得很好,而且很容易解析,我唯一的问题是性能,这当然是相当慢的

我想知道是否有一种方法可以改进这一点,因为我只需要按键查找,然后停止循环,因此,如果条目位于文件的开头,它会很快完成,但如果位于结尾,则需要一段时间

我可以通过给它一个随机的起始线来平衡这一点,但算法仍然是在。。。所以我不确定这是否真的值得


有什么方法可以改进我的顺序解析算法吗?

为什么不将csv转换为普通数据库呢。甚至sqlexpress也可以。

当然可以

假设你按字母顺序排列。 然后,从中间开始。 每次迭代,移动到顶部或底部的中间;哪个有合适的钥匙

该算法具有OLOGN


这就是所谓的二进制搜索,这也是迈克·克里斯汀森在评论中的建议

将建议您将一个40Mb文件拆分为几个较小的文件。
而且使用可以提高文件处理性能

首先:读取巨大的CSV文件,因此我正在解析一个40MB的CSV文件。。我这里有10+GB的空间分隔文件-你会怎么称呼这些文件

另外:文件的大小是不相关的,您通常会逐行处理它们

我唯一的问题是性能,这当然是相当缓慢的

定义。你认为什么东西慢?正确完成后,解析它们的速度相当快

我想知道是否有一种方法可以改进这一点,因为我只需要按我找到的键和 然后停止循环,这样,如果条目位于文件的最前端,它就会停止循环 完成得很快,但如果是在最后,则需要一段时间

不使用CSV文件?60多年前,人们为此发明了数据库

有什么方法可以改进我的连续解析算法吗

你的意思是,除了将解析拉到一个单独的线程中,并使用一个可能没有的高效代码之外——没有人知道

理论上你可以:

在一个线程上读取,具有适当的缓冲区更少IO=更快

将字段拆分为线程2(可选)

使用任务来解析字段,每行一个字段,以便使用所有处理器

我目前正在处理大约10000个大小为两位数千兆字节的文件,并且。。。我走这条路,必须按照特定的顺序处理它们,才能充分使用我的电脑

这会给你带来很多好处——说真的,一个40mb的文件应该在0.x秒0.5-0.6内加载


但这仍然是非常低效的。你为什么不像所有人那样将文件加载到数据库中?CSV和某些传输格式一样好,它就像一个数据库。

您可以将CSV加载到DataTable中,并使用比循环更快的可用操作


将其加载到数据库并对其执行操作是另一个选项,我相信这是按顺序读取CSV文件的最快方法。可能还有其他方法可以从CSV中提取数据,但如果您仅限于此方法,则此解决方案可能适合您

const int BUFFER_SIZE = 0x8000;  //represents 32768 bytes
public unsafe void parseCSV(string filePath)
{
     byte[] buffer = new byte[BUFFER_SIZE];
     int workingSize = 0; //store how many bytes left in buffer
     int bufferSize = 0; //how many bytes were read by the file stream
     StringBuilder builder = new StringBuilder();
     char cByte; //character representation of byte
     using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
     {
         do
         {
              bufferSize = fs.Read(buffer, 0, BUFFER_SIZE);
              workingSize = bufferSize;
              fixed (byte* bufferPtr = buffer)
              {
                   byte* workingBufferPtr = bufferptr;
                   while (workingSize-- > 0)
                   {
                        switch (cByte = (char)*workingBufferPtr++)
                        {
                            case '\n':
                                break;
                            case '\r':
                            case ',':
                                builder.ToString();
                                builder.Clear();
                                break;
                            default:
                                builder.Append(cByte);
                                break;
                        }
                   }
              }
         } while (bufferSize != 0);
     }
}
说明:

将文件读入字节缓冲区。这将使用基本的Filestream类来完成,该类提供对始终快速读取的访问 不安全代码。虽然我通常建议不要使用不安全的代码,但在遍历任何类型的缓冲区时,使用指针都会带来加速。 StringBuilder,因为我们将把字节连接到可工作的字符串中,以便对键进行测试。到目前为止,StringBuilder是将字节附加在一起并从中获得可用字符串的最快方法。
请注意,这种方法相当麻烦,但如果您处理引号,您可以轻松修改我发布的代码来处理修剪。

如果您可以按该键对文件进行排序,则可以使用二进制搜索来提高速度。首先,对于CSV文件来说,40MB并不是那么大。第二,您目前使用的代码中有哪些显然花费了这么长时间?我不认为它会那么慢,这意味着你要么有不切实际的期望,要么你的代码中有更严重的问题。1秒?你为什么想要比一秒钟更快?我只是想知道是否有可能更快的方法,因为我很好奇-你为什么不发布你的代码,这样人们就可以提出一些建议。说我如何让它跑得更快?不用说它是什么,也没什么好做的。CSV文件是由客户端删除的,他们从excel中导出并定期更新,我可以检查文件的修改日期,如果更新了,我可以创建一个数据库。这是一个解决方案,虽然不是我正在寻找的,但如果CSV变得太慢,我可能会尝试以下方法:啊!有序CSV。。。这是可行的,但是CSV文件没有排序,解析文件以排序可能不值得,因为我可以按照@Lakis所说的那样做。但我喜欢这个主意:我甚至都没有
要知道这是可能的,尽管算法本身仍然在运行,但由于并行性,计算速度会更快:我会试试这个!谢谢如果你的文件是在一个硬盘上,这很可能会减慢速度。虽然这里的所有改进都是有用的,但值得向OP强调的是,在你的具体情况下,这将需要大量的工作才能正确,你会发现,由于你没有足够的数据或处理需求,在几分之一秒的最大值上几乎没有什么改进。最重要的是,这也是我所说的,这实际上需要一个索引和类似数据库的方法——从CSV开始这样做不是正确的方法。我不确定——真的。这在按分和按磅分类中可能是最快的,您忽略了并非所有字段都是字符串的事实,即可能需要额外的转换。最后,你可能会节省很多钱-很少的字符串分裂。我会使用FileStream nie大缓冲区上的BUfferedStream,比如半兆字节,使用字符串拆分,然后从那里获取它——假设大多数字段都被解析,结果被放入一个类中@TomTom我在104MB CSV上做了一些初步测试。我提出解决方案的方式实际上是执行速度最慢的,大约5%。安全代码数组索引和带缓冲流512KB缓冲区的安全代码速度更快,大致相等。我不确定您所指的字符串拆分是什么,因为它是字符串操作,仍然需要转换。这正是我所指的。由于大部分时间将花费在对流和字符串操作上,因此即使节省50%的负载,也不会产生任何有效差异;过早优化。不安全的代码没有真正的收益,我认为没有检查。这在很大程度上取决于解析的复杂程度。