使用动态列数解析大分隔文件

时间:2010-05-06 16:07:02

标签: c# .net parsing large-files delimited

在解析文件之前,当列未知时解析分隔文件的最佳方法是什么?

文件格式为Rightmove v3(.blm),结构如下:

#HEADER#
Version : 3
EOF : '^'
EOR : '~'
#DEFINITION#
AGENT_REF^ADDRESS_1^POSTCODE1^MEDIA_IMAGE_00~ // can be any number of columns
#DATA#
agent1^the address^the postcode^an image~
agent2^the address^the postcode^^~      // the records have to have the same number of columns as specified in the definition, however they can be empty
etc
#END#

文件可能非常大,我的示例文件是40Mb,但它们可能是几百兆字节。下面是在我意识到列是动态的之前我开始的代码,我正在打开一个文件流,因为我读到这是处理大文件的最佳方法。我不确定我的想法是将每条记录放在一个列表中,然后处理是好的,不知道这是否适用于这么大的文件。

List<string> recordList = new List<string>();

try
{
    using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
    {
        StreamReader file = new StreamReader(fs);
        string line;
        while ((line = file.ReadLine()) != null)
        {
            string[] records = line.Split('~');

            foreach (string item in records)
            {
                if (item != String.Empty)
                {
                    recordList.Add(item);
                }
            }

        }
    }
}
catch (FileNotFoundException ex)
{
    Console.WriteLine(ex.Message);
}

foreach (string r in recordList)
{
    Property property = new Property();

    string[] fields = r.Split('^');

    // can't do this as I don't know which field is the post code
    property.PostCode = fields[2];
    // etc

    propertyList.Add(property);
}

有关如何做得更好的任何想法?如果有帮助,那就是C#3.0和.Net 3.5。

谢谢,

Annelie

2 个答案:

答案 0 :(得分:1)

你可以通过几种方式做到这一点。

  1. 如果对象上的属性与数据文件中的列具有相同的名称,则可以使用反射来确定哪些列应与哪些属性匹配。
  2. 如果对象上的属性具有不同的名称,那么您可以编写一个自定义映射架构,表示“对于列X,分配给属性Y”。
  3. 您可以为对象属性创建自定义属性,以指示它们映射到哪个列名称,并使用反射来读取这些属性。
  4. 所有这些步骤都预先假定数据文件中的列名对于它们所代表的数据是相同的(即,ADDRESS_1将始终是“地址第一行”数据的列名)。

答案 1 :(得分:1)

如果您可以在开头删除部分行(标题内容和#xxx#行),那么它只是一个以^作为分隔符的csv文件,因此任何CSV reader class会做的。