【问题标题】:How can i sort large csv file without loading to memory如何在不加载到内存的情况下对大型 csv 文件进行排序
【发布时间】:2011-09-09 11:39:12
【问题描述】:

我有 20GB+ 的 csv 文件,如下所示:

**CallId,MessageNo,Information,Number** 
1000,1,a,2
99,2,bs,3
1000,3,g,4
66,2,a,3
20,16,3,b
1000,7,c,4
99,1,lz,4 
...

我必须按 CallId 和 MessageNo asc 排序这个文件。 (一种方法是加载数据库->排序->导出)

如何在不将所有行加载到 C# 中的内存的情况下对该文件进行排序? (比如使用流式阅读器逐行)

您知道解决方案库吗? 我等待你的建议, 谢谢

【问题讨论】:

    标签: c# file sorting csv


    【解决方案1】:

    您应该使用操作系统排序命令。通常只是

    sort myfile
    

    接着是一些神秘的开关。这些命令通常适用于大文件,并且通常可以选择在其他物理硬盘上指定临时存储。请参阅此 previous question 和 Windows sort 命令 "man" page。由于 Windows 排序不足以解决您的特定排序问题,您可能需要使用 GNU coreutils,它将 linux sort 的强大功能带到 Windows。

    解决方案

    这是您需要做的。

    1. 下载GNU Coreutils Binaries ZIP并将sort.exe从bin文件夹解压到你机器上的某个文件夹,例如你要排序的文件所在的文件夹。
    2. 下载GNU Coreutils Dependencies ZIP并将两个.dll文件解压到与sort.exe相同的文件夹中

    现在假设您的文件如下所示:

    1000,1,a,2
    99,2,bs,3
    1000,3,g,4
    66,2,a,3
    20,16,3,b
    1000,7,c,4
    99,1,lz,4 
    

    你可以在命令提示符下写:

    sort.exe yourfile.csv -t, -g
    

    会输出:

    20,16,3,b
    66,2,a,3
    99,1,lz,4
    99,2,bs,3
    1000,1,a,2
    1000,3,g,4
    1000,7,c,4
    

    more command options here。如果这是您想要的,请不要忘记使用-o 开关提供输出文件,如下所示:

    sort.exe yourfile.csv -t, -g -o sorted.csv
    

    【讨论】:

    • 在哪个 OS 排序命令能够解析 CSV 文件并按特定字段排序?
    • 据我所知 Linux;我也认为是 Windows。
    • 我相信开发人员使用 Linux 提出 C# 问题的可能性很小,无论如何,如果您 100% 确定有关 linux 而不确定有关 Windows,则应在答案中指出这一点。这是我的观点。
    • 好点,但您可以在窗口中使用 Linux 排序,但会有些麻烦。
    • 我知道您可以对位置字节/列号进行排序,但是如果您想对第三个字段进行排序怎么办?有开关可以做到这一点吗?
    【解决方案2】:

    这是一个经典的算法问题,称为External Sorting

    当被排序的数据不适合时需要外部排序 进入计算设备的主存储器(通常是 RAM),而不是 它们必须驻留在速度较慢的外部存储器(通常是硬盘驱动器)中。 外部排序通常使用排序合并策略。在排序中 阶段,读取足够小的数据块以适合主存储器, 排序,并写出到一个临时文件。在合并阶段, 排序后的子文件合并为一个更大的文件

    .NET Framework 的角度来看,我建议利用.NET 4 功能-Memory Mapped Files 将文件的部分内容作为单独的视图投影到内存中。

    Here is 一个 Java 外部归并排序的例子,你应该可以很容易地将它应用到 C# 中:

    编辑:添加了上述 Java 示例的使用示例以展示其简单性

    Comparator<String> comparator = new Comparator<String>() 
    {                         
      public int compare(String r1, String r2)
      {                                 
         return r1.compareTo(r2);
      }
    };                 
    
    List<File> l = sortInBatch(new File(inputfile), comparator);                
    mergeSortedFiles(l, new File(outputfile), comparator); 
    

    【讨论】:

      【解决方案3】:

      你应该使用 python 来完成这类任务:)

      在此处查看类似的完整工作示例:

      Python: How to read huge text file into memory

      编辑:

      在同一个答案中,如果您的文件确实比可用的 RAM 量大得多,则有一个有用的链接:http://code.activestate.com/recipes/466302/

      【讨论】:

      • 我无法将 24GB 以上的文件加载到内存(是内存问题)
      • Oguzh4n,请阅读该答案,还有一篇文章的链接,介绍如何在文件大于可用 RAM 时执行此操作:code.activestate.com/recipes/466302
      猜你喜欢
      • 2019-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-26
      • 2011-08-26
      相关资源
      最近更新 更多