Чтение csv-файла методом c #

#c#

#c#

Вопрос:

Я стремлюсь прочитать файл csv в моем методе c #. этот 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
 

Комментарии:

1. Ваш вопрос кажется немного расплывчатым. Какой тип значений приводит к сбою вашего метода? Вы всегда намерены использовать 2 значения, разделенные запятыми metadata[1] ?

2. Когда ваше поле содержит разделитель — поле в CSV-файле должно быть «квалифицированным», в основном заключенным в квоты — kb.blackbaud.com/knowledgebase/Article/75155 . Похоже, что для уточнения в вашем csv используются символы ‘[‘ и ‘]’. Библиотека CSVHelper позволяет вам устанавливать квалификатор — искать конфигурацию. Поле кавычек (по умолчанию это двойные квоты)

3. я обновил вопрос значением выборки, когда он не удался

4. [ и ] разрешены ли они внутри значения? Если да, то как вы избегаете их, чтобы отличать от тех, которые используются для цитирования полей?

5. вот что я не могу этого сделать .. вот где я терплю неудачу

Ответ №1:

Это код, который я использую для синтаксического анализа строки 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 != "," amp;amp; 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) != "" amp;amp; (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);
}
 

Он правильно обрабатывает поля, заключенные в кавычки.