首页 > 解决方案 > 用c#方法读取csv文件

问题描述

我的目标是在我的 c# 方法中读取一个 csv 文件。此 csv 文件未定义,它可以有 n 列。始终保持不变的一件事是 csv 文件中只有两行。一个是标题行,另一个是值行。当我的值是字符串值时,我的以下方法可以正常工作,但当我的值之一是这样的 [test,test1,test2] 时会失败。我尝试使用 Csv 助手类,但我做不到。有人可以建议我应该如何处理吗?

元数据是我从 StreamReader 读取的行列表
private void AddValuesToTable( DynamicTableEntity tableEntry, List<string> metadata )
        {
           
            var headers = metadata[0].Split( "," );
            var values = metadata[1].Split( "," );
            for( int i = 0; i < headers.Count(); i++ )
            {
                tableEntry.Properties.Add( headers[i].ToString(), EntityProperty.CreateEntityPropertyFromObject( values[i] ) );
            }
        }

样本值:

columnA,columnB,columnC
valA,[testa,testb],valc

标签: c#

解决方案


这是我用来解析 CSV 行的代码。

private static string Peek(this string source, int peek) => (source == null || peek < 0) ? null : source.Substring(0, source.Length < peek ? source.Length : peek);
private static (string, string) Pop(this string source, int pop) => (source == null || pop < 0) ? (null, source) : (source.Substring(0, source.Length < pop ? source.Length : pop), source.Length < pop ? String.Empty : source.Substring(pop));

public static string[] ParseCsvLine(this string line)
{
    return ParseCsvLineImpl(line).ToArray();
    IEnumerable<string> ParseCsvLineImpl(string l)
    {
        string remainder = line;
        string field;
        while (remainder.Peek(1) != "")
        {
            (field, remainder) = ParseField(remainder);
            yield return field;
        }
    }
}

private const string DQ = "\"";

private static (string field, string remainder) ParseField(string line)
{
    if (line.Peek(1) == DQ)
    {
        var (_, split) = line.Pop(1);
        return ParseFieldQuoted(split);
    }
    else
    {
        var field = "";
        var (head, tail) = line.Pop(1);
        while (head != "," && head != "")
        {
            field += head;
            (head, tail) = tail.Pop(1);
        }
        return (field, tail);
    }
}

private static (string field, string remainder) ParseFieldQuoted(string line)
{
    var field = "";
    var head = "";
    var tail = line;
    while (tail.Peek(1) != "" && (tail.Peek(1) != DQ || tail.Peek(2) == DQ + DQ))
    {
        if (tail.Peek(2) == DQ + DQ)
        {
            (head, tail) = tail.Pop(2);
            field += DQ;
        }
        else
        {
            (head, tail) = tail.Pop(1);
            field += head;
        }
    }
    if (tail.Peek(2) == DQ + ",")
    {
        (head, tail) = tail.Pop(2);
    }
    else if (tail.Peek(1) == DQ)
    {
        (head, tail) = tail.Pop(1);
    }
    return (field, tail);
}

它正确处理带引号的字段。


推荐阅读