【问题标题】:filehelpers - Parsing variable line lengthfilehelpers - 解析可变行长
【发布时间】:2014-05-31 07:05:56
【问题描述】:

我必须解析 (C#) 一个 .CSV 文件,其中包含变量“宽度”和 2 行标题信息(第一行是名称,第二行是单位)。

数据如下:

Example1.CSV:

"timestamp","NAME_1","NAME_2","NAME_3","NAME_4"
"ms","unit_1","unit_2","unit_3","unit_4"
0.01,1.23,4.56,7.89,0.12
0.02,1.23,4.66,7.89,0.11
0.03,1.23,4.76,7.89,0.11
0.04,56.23,4.86,7.89,0.12

Example2.CSV:

"timestamp","NAME_1","NAME_2","NAME_3","NAME_4","NAME_5",...,"NAME_N"
"ms","unit_1","unit_2","unit_3","unit_4","unit_5",...,"unit_N"
0.01,1.23,4.56,7.89,0.12,0.13,...,0.27
0.02,1.23,4.66,7.89,0.12,0.13,...,0.22
0.03,1.23,4.76,7.89,0.11,0.13,...,0.24
0.04,56.23,4.86,7.89,0.12,0.13,...,0.29

N 是表格的“宽度”(值可以达到 128 或更大)。我打算用Filehelpers

我曾想过使用[FieldOptional()]——但这很不方便,尤其是当“宽度”可变时...

我目前的尝试看起来像

[IgnoreFirst(2)]
[DelimitedRecord(",")]
public sealed class LogData
{

    public Double ts;

    public Double Field1;

    [FieldNullValue(0.0)]
    [FieldOptional()]
    public Double Field2;

    [FieldNullValue(0.0)]
    [FieldOptional()]
    public Double Field3;

    // and so on
}

任何有关“如何解决可变宽度”的帮助 - 以更优雅的方式解决问题 - 非常感谢您!

【问题讨论】:

  • 阅读完 CSV 文件后,您打算如何使用该模型?
  • 模型用于绘制和过滤数据。要么我正在使用来自 LogData[] res = engine.ReadFile(@"..\\..\\testdata.csv"); 的 Array-Result,要么我正在将其转换为 DataTable - 我打算让性能测试来决定。

标签: c# csv width line filehelpers


【解决方案1】:

如果您打算将文件转换为 DataTable,有更好的选择

请使用 FileHelpers 库的 CsvEngine。见下面的代码sn-p:

using (MemoryStream stream = new MemoryStream(_fileContent)) //file content can be file as byte array
            {
                TextReader reader = new StreamReader(stream);
string path = "C:\\Sample.csv";
                CsvEngine csvEngine = new CsvEngine("Model", ',', path);
                var dataTable = csvEngine.ReadStreamAsDT(reader);
//Do whatever with dataTable

}

这里的示例文件可以是 csv 文件,也可以是包含您要处理的 csv 文件的标题的文本文件。 DataTable的列将根据示例文件的标题命名

干杯

【讨论】:

  • 轰炸机!甚至第一行也会自动添加为dataTable.Columns[i].ColumnName。知道如何将列特定的单元信息也存储在DataTable 中(.CSV 中的第二行)?也许滥用ColumnName 以及自定义转换器和自定义分隔符“|||”?
  • @Ben 如果值的个数与列数相同,则可以将CSV第二行中的单位信息作为DataTable中的第二行。如果您需要任何自定义格式的相同内容,则需要进行一些调整。
  • 遗憾的是,这是没有选择的,因为我想在之后将 [1] 值转换为 Double DataTable (需要处理值的绘图和处理)。 [1]stackoverflow.com/questions/9028029/…
【解决方案2】:

您可以使用可选的数组字段。我认为您需要使用 FileHelpers 2.9.9。

[IgnoreFirst(2)]
[DelimitedRecord(",")]
public class LogData
{
    public Double TimeStamp;

    [FieldNullValue(0.0)]
    [FieldOptional, FieldArrayLength(0, 100)]
    public Double[] ManyFields;
}

这是一个工作示例。

class Program
{
    static String content = 
         @"""timestamp"",""NAME_1"",""NAME_2"",""NAME_3"",""NAME_4""
         ""ms"",""unit_1"",""unit_2"",""unit_3"",""unit_4""
         0.01,1.23,4.56,7.89,0.12
         0.02,1.23,4.66,7.89,0.11
         0.03,1.23,4.76,7.89,0.11
         0.04,56.23,4.86,7.89,0.12";

    private static void Main()
    {
        var engine = new FileHelperEngine<LogData>();
        var records = engine.ReadString(content);
        Assert.AreEqual(0.01, records[0].TimeStamp);
        Assert.AreEqual(1.23, records[0].ManyFields[0]);
        Assert.AreEqual(4.56, records[0].ManyFields[1]);
        Assert.AreEqual(7.89, records[0].ManyFields[2]);
        Assert.AreEqual(0.12, records[0].ManyFields[3]);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-13
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 2012-05-24
    • 1970-01-01
    相关资源
    最近更新 更多