【问题标题】:Working with Data from csv file处理来自 csv 文件的数据
【发布时间】:2013-07-08 23:50:29
【问题描述】:

我有一个大的 CSV 文件 (50000 * 25),它本质上是一个包含数字和字母数字字段的数据表。

我在代码项目中使用了 Lumenworks 的“A Fast CSV Reader”。 (链接http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader?msg=4600509#xx4600509xx

我正在寻找稍后处理数据的最有效方法,我必须对部分数据进行求和、平均等。

到目前为止我的代码:

static void Main()
    {
        // open the file "data.csv" which is a CSV file with headers
        using (CsvReader csv =
               new CsvReader(new StreamReader(@"c:\Temp\Extrinsic_Hourly.csv"), true))
        {
            int fieldCount = csv.FieldCount;
            csv.SupportsMultiline = false;

            List<string> filedata = new List<string>();
            string[] headers = csv.GetFieldHeaders();



            while (csv.ReadNextRecord())
            {
                for (int i = 0; i < fieldCount; i++)        
                {
                //if (headers[i] == "PowerPrice")
                    filedata.Add(csv[i]);
                }
            }


            File.WriteAllLines(@"c:\Temp\test.txt", filedata); 


        }

最后一行只是检查导入是否有效。这工作正常并且相对较快,但现在我有这个庞大的列表并且很难使用。如果我现在需要对第 13 列进行平均,我会卡住如何做到这一点。

filedata.column(13).Average()

显然不起作用,尤其是因为它的所有字符串。

最好将结构化的数据导入到一个类中,或者将大二维列表的整个列转换为一维列表,如果它们是数字,我还可以将字符串转换为双精度值。

如果我以后必须根据来自不同列的条件对整个列或列的一部分执行算术运算,最好的方法是什么,例如第 1 列有日期,我可能想对第 2 列求和个月。

谢谢。

【问题讨论】:

  • 所以你建议创建一个自定义类,然后在导入时转换为日期、字符串、双精度等,然后它会很容易使用。还是您认为将所有内容作为字符串导入然后从大列表中转换更快?谢谢
  • 每条记录读的时候最好转换一下,这样可以节省很多内存。以数字 123456 为例,如果将其存储为字符串,则它占用的内存至少是存储为整数的相同信息的 3 倍......

标签: c#


【解决方案1】:

最直接的方法是使用DataTable。例如:

DataTable tblCSV = new DataTable("CSV");
var fileInfo = new System.IO.FileInfo(fullPath);
var encoding = Encoding.GetEncoding(437); // use the correct encoding
using (var reader = new System.IO.StreamReader(fullPath, encoding))
{
    //reader.ReadLine(); // skip all lines but header+data
    Char quotingCharacter = '\0';//'"';
    Char escapeCharacter = quotingCharacter;
    using (var csv = new CsvReader(reader, true, Importer.FieldDelimiter, quotingCharacter, escapeCharacter, '\0', ValueTrimmingOptions.All))
    {
        csv.MissingFieldAction = MissingFieldAction.ParseError;
        csv.DefaultParseErrorAction = ParseErrorAction.RaiseEvent;
        csv.ParseError += csv_ParseError;
        csv.SkipEmptyLines = true;
        try
        {
            // load into DataTable
            tblCSV.Load(csv, LoadOption.OverwriteChanges, csvTable_FillError);

然后你可以使用 Linq-To-DataSet:

double avg = tblCSV.AsEnumerable()
    .Select(r => int.Parse(r.Field<string>(13)))
    .Average();

【讨论】:

  • 请记住,DataTable 对象的内存占用很大,也许对于这么多数据,最好创建可以处理的专用轻量级(列表?)结构并行算法。
  • 事实证明,对于我必须使用数据表的文件,它确实减慢了它的速度,我现在将它加载到自定义类中。不过谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 2019-09-12
  • 1970-01-01
  • 2016-09-12
  • 2020-01-06
  • 1970-01-01
相关资源
最近更新 更多