Работа с запятыми в файле CSV


472

Я ищу предложения о том, как обрабатывать CSV-файл, который создается, затем загружается нашими клиентами и может иметь запятую в значении, таком как название компании.

Вот некоторые идеи, которые мы рассматриваем: цитируемые идентификаторы (значение, значения, и т. Д.) Или использование | вместо запятой. Самая большая проблема заключается в том, что нам нужно сделать это проще, иначе клиент этого не сделает.


клиент пишет и загружает его
Bob The Janitor

1
Вот решение для управления внутри коммод в CSV-файле. Посетите stackoverflow.com/questions/9889225/…
Хасан Абрар

на iOS, по сути, вы должны использовать github.com/Flinesoft/CSVImporter
Fattie

3
Обратите внимание, что этот QA старый. В настоящее время csv означает RFC 4180 и все.
Толстяк

У меня точно такая же проблема, пытаясь суммировать столбец в CSV-файле, который разделен запятой. Нет проблем с командой awk. К сожалению, некоторые ячейки могут содержать запятые (например, в адресе), другие ячейки не будут. Ищете совместимое с Linux решение, но не знаете, с чего начать.
зелень

Ответы:


223

Как уже говорили другие, вам нужно избегать значений, которые включают кавычки. Вот небольшой CSV-ридер на C♯, который поддерживает значения в кавычках, включая встроенные кавычки и возврат каретки.

Кстати, это проверенный модулем код. Я публикую его сейчас, потому что этот вопрос, кажется, часто поднимается, и другие могут не захотеть целую библиотеку, когда подойдет простая поддержка CSV.

Вы можете использовать его следующим образом:

using System;
public class test
{
    public static void Main()
    {
        using ( CsvReader reader = new CsvReader( "data.csv" ) )
        {
            foreach( string[] values in reader.RowEnumerator )
            {
                Console.WriteLine( "Row {0} has {1} values.", reader.RowIndex, values.Length );
            }
        }
        Console.ReadLine();
    }
}

Вот классы. Обратите внимание, что вы также можете использовать эту Csv.Escapeфункцию для написания действительного CSV.

using System.IO;
using System.Text.RegularExpressions;

public sealed class CsvReader : System.IDisposable
{
    public CsvReader( string fileName ) : this( new FileStream( fileName, FileMode.Open, FileAccess.Read ) )
    {
    }

    public CsvReader( Stream stream )
    {
        __reader = new StreamReader( stream );
    }

    public System.Collections.IEnumerable RowEnumerator
    {
        get {
            if ( null == __reader )
                throw new System.ApplicationException( "I can't start reading without CSV input." );

            __rowno = 0;
            string sLine;
            string sNextLine;

            while ( null != ( sLine = __reader.ReadLine() ) )
            {
                while ( rexRunOnLine.IsMatch( sLine ) && null != ( sNextLine = __reader.ReadLine() ) )
                    sLine += "\n" + sNextLine;

                __rowno++;
                string[] values = rexCsvSplitter.Split( sLine );

                for ( int i = 0; i < values.Length; i++ )
                    values[i] = Csv.Unescape( values[i] );

                yield return values;
            }

            __reader.Close();
        }
    }

    public long RowIndex { get { return __rowno; } }

    public void Dispose()
    {
        if ( null != __reader ) __reader.Dispose();
    }

    //============================================


    private long __rowno = 0;
    private TextReader __reader;
    private static Regex rexCsvSplitter = new Regex( @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))" );
    private static Regex rexRunOnLine = new Regex( @"^[^""]*(?:""[^""]*""[^""]*)*""[^""]*$" );
}

public static class Csv
{
    public static string Escape( string s )
    {
        if ( s.Contains( QUOTE ) )
            s = s.Replace( QUOTE, ESCAPED_QUOTE );

        if ( s.IndexOfAny( CHARACTERS_THAT_MUST_BE_QUOTED ) > -1 )
            s = QUOTE + s + QUOTE;

        return s;
    }

    public static string Unescape( string s )
    {
        if ( s.StartsWith( QUOTE ) && s.EndsWith( QUOTE ) )
        {
            s = s.Substring( 1, s.Length - 2 );

            if ( s.Contains( ESCAPED_QUOTE ) )
                s = s.Replace( ESCAPED_QUOTE, QUOTE );
        }

        return s;
    }


    private const string QUOTE = "\"";
    private const string ESCAPED_QUOTE = "\"\"";
    private static char[] CHARACTERS_THAT_MUST_BE_QUOTED = { ',', '"', '\n' };
}

2
Вам также может понадобиться перевести \ r \ n для соответствия Windows, в зависимости от вашего приложения.
Мандрагора

3
@NadaNaeem, хотите уточнить?
Harpo

он неправильно
учитывает

-1 OP не указывает язык, который создает файл. Если любой другой программист придет сюда в поисках решения на любом языке, кроме C #, он не найдет решение, которое можно использовать в этом ответе.
Бен Легжеро

8
@ BenC.R.Leggiero, тогда я полагаю, что вы также должны понизить вопрос, так как он не отвечает по вашим стандартам. Как таковой, код представляет собой формальную реализацию простой спецификации и может быть легко переведен на любой широко используемый язык.
Гарпо

395

На 2017 год csv полностью указан - RFC 4180.

Это очень распространенная спецификация, полностью охватываемая многими библиотеками ( пример ).

Просто используйте любую легкодоступную библиотеку CSV - то есть RFC 4180.


На самом деле есть спецификация для формата CSV и способ обработки запятых:

Поля, содержащие разрывы строк (CRLF), двойные кавычки и запятые, должны быть заключены в двойные кавычки.

http://tools.ietf.org/html/rfc4180

Итак, чтобы иметь значения fooи bar,baz, вы делаете это:

foo,"bar,baz"

Еще одно важное требование для рассмотрения (также из спецификации):

Если двойные кавычки используются для включения полей, то двойная кавычка, появляющаяся внутри поля, должна быть экранирована, предшествуя другой двойной кавычке. Например:

"aaa","b""bb","ccc"

120
«Поля, содержащие разрывы строк (CRLF), двойные кавычки и запятые, должны быть заключены в двойные кавычки».
Эли

42
«Если двойные кавычки используются для включения полей, то двойная кавычка, появляющаяся внутри поля, должна быть исключена, если перед ней стоит еще одна двойная кавычка».
С. Дракон 76

11
Не совсем специфика, но все же, вероятно, удобно. В нем говорится ... «Не существует формальной спецификации, которая допускает широкое разнообразие интерпретаций файлов CSV. В этом разделе описывается формат, которому, как представляется, следует большинство реализаций».
Джастин Кларк

5
Кроме того, не забывайте, что, несмотря на название, значения CSV в строке могут разделяться не только запятыми - по крайней мере, на платформах Windows. Это зависит от текущих региональных настроек (intl.cpl в командной строке «Дополнительные настройки»), в частности, разделитель списка: System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator.
LXA

4
Пожалуйста, поместите соответствующую информацию в этом ответе, в дополнение к ссылке, на А) Удалите большинство вышеупомянутых комментариев (и моих), Б) Сэкономьте гораздо больше людей, чем отвечающий, время, чтобы перейти на еще одну страницу и найти соответствующую данные, в) Предотвратить Ссылку Гниль.
user66001

76

Формат CSV использует запятые для разделения значений, значения, содержащие возврат каретки, переводы строки, запятые или двойные кавычки, заключаются в двойные кавычки. Значения, содержащие двойные кавычки, заключаются в кавычки, и каждая буквальная кавычка экранируется непосредственно предшествующей кавычкой: например, 3 значения:

test
list, of, items
"go" he said

будет закодирован как:

test
"list, of, items"
"""go"" he said"

Любое поле может быть заключено в кавычки, но только те поля, которые содержат запятые, CR / NL или кавычки, должны быть заключены в кавычки.

Не существует реального стандарта для формата CSV, но почти все приложения следуют соглашениям, описанным здесь . RFC, который упоминался в другом месте, не является стандартом для CSV, это RFC для использования CSV в MIME и содержит некоторые нетрадиционные и ненужные ограничения, которые делают его бесполезным вне MIME.

Причиной, которую многие CSV-модули, которые я видел, не приспосабливают, является тот факт, что несколько строк могут быть закодированы в одном поле, что означает, что вы не можете предполагать, что каждая строка является отдельной записью, либо вы не должны допускать переносы в вашем данные или будьте готовы справиться с этим.


40

Положите двойные кавычки вокруг строк. Это обычно то, что делает Excel .

Ала Эли,

вы избегаете двойных кавычек как двух двойных кавычек. Например, "test1", "foo", "bar", "test2"


в основном та же концепция, что и в цитируемых идентификаторах
Bob The Janitor

1
вы избегаете двойных кавычек как двух двойных кавычек. Например, "test1", "foo" "bar", "test2"
Eli

Простое размещение двойных кавычек вокруг строки не работает, когда сразу за «следует запятая»
MondKin

9

Вы можете поставить двойные кавычки вокруг полей. Мне не нравится этот подход, поскольку он добавляет еще один специальный символ (двойная кавычка). Просто определите escape-символ (обычно с обратной косой чертой) и используйте его везде, где вам нужно что-то экранировать:

данные, больше данных, больше данных \, даже больше

Вам не нужно пытаться сопоставлять кавычки, и у вас меньше исключений для разбора. Это также упрощает ваш код.


3
Быстро и грязно, но не работает, если у вас есть запись, содержащая «\»
Sarp Kaya

1
Sarp, вот почему двойной \\ - это экранированный обратный слеш, поскольку теперь он становится еще одним специальным символом.
Grungondola

1
Это работает, но не CSV. Это DSV .
TRiG

8

Через nuget доступна библиотека для работы с практически любым правильно сформированным CSV (.net) - CsvHelper

Пример для сопоставления с классом:

var csv = new CsvReader( textReader );
var records = csv.GetRecords<MyClass>();

Пример для чтения отдельных полей:

var csv = new CsvReader( textReader );
while( csv.Read() )
{
    var intField = csv.GetField<int>( 0 );
    var stringField = csv.GetField<string>( 1 );
    var boolField = csv.GetField<bool>( "HeaderName" );
}

Разрешение клиенту управлять форматом файла:
, это стандартный разделитель полей, "это стандартное значение, используемое для экранирования полей, которые содержат разделитель, кавычку или конец строки.

Использовать (например) #для полей и 'для экранирования:

var csv = new CsvReader( textReader );
csv.Configuration.Delimiter = "#";
csv.Configuration.Quote = ''';
// read the file however meets your needs

Больше документации


3
Было бы предпочтительнее, если бы вы включили пример использования CsvHelperбиблиотеки для решения проблемы ОП.
Джордж Стокер

Почему почти все в .Net должно быть "Помощником" ... слово почти бессмысленно ... как "Менеджер".
Бытев

5

Как упомянуто в моем комментарии к ответу гарпо, его решение хорошо и работает в большинстве случаев, однако в некоторых сценариях, когда запятые как непосредственно примыкают друг к другу, он не разделяется на запятые.

Это связано с тем, что строка Regex неожиданно ведет себя как строка vertabim. Для правильного поведения всех «символов» в строке регулярного выражения необходимо экранировать вручную без использования экранирования vertabim.

То есть. Регулярное выражение должно быть таким, используя ручные экранированные символы:

",(?=(?:[^\"\"]*\"\"[^\"\"]*\"\")*(?![^\"\"]*\"\"))"

что переводится на ",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"

При использовании строки vertabim @",(?=(?:[^""]*""[^""]*"")*(?![^""]*""))"она ведет себя следующим образом, как вы можете видеть, если вы отлаживаете регулярное выражение:

",(?=(?:[^"]*"[^"]*")*(?![^"]*"))"

Итак, в заключение, я рекомендую решение Harpo, но остерегайтесь этой маленькой ошибки!

Я включил в CsvReader немного необязательный отказоустойчивый, чтобы уведомить вас, если эта ошибка происходит (если у вас есть заранее известное количество столбцов):

if (_expectedDataLength > 0 && values.Length != _expectedDataLength) 
throw new DataLengthException(string.Format("Expected {0} columns when splitting csv, got {1}", _expectedDataLength, values.Length));

Это может быть введено через конструктор:

public CsvReader(string fileName, int expectedDataLength = 0) : this(new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
    _expectedDataLength = expectedDataLength;
}

Как бы вы справились с обработкой строки заголовка? я пытаюсь сопоставить csv объектам C #, которые являются всеми типами, но строка заголовка разбивает его, потому что все его строки ...
tCoe

Разве не так [^""]же, как [^"]? Дублирование символа в спецификации класса символа является избыточным, верно?
Минь

4

Добавьте ссылку на Microsoft.VisualBasic (да, он говорит VisualBasic, но он работает и в C # точно так же - помните, что в конце все это просто IL).

Используйте Microsoft.VisualBasic.FileIO.TextFieldParserкласс для разбора файла CSV. Вот пример кода:

 Dim parser As TextFieldParser = New TextFieldParser("C:\mar0112.csv")
 parser.TextFieldType = FieldType.Delimited
 parser.SetDelimiters(",")      

   While Not parser.EndOfData         
      'Processing row             
      Dim fields() As String = parser.ReadFields         
      For Each field As String In fields             
         'TODO: Process field                   

      Next      
      parser.Close()
   End While 

Да, это очень полезный класс в несколько неудачном пространстве имен ;-). Однако, чтобы ответить на исходный вопрос, вы также должны установить, parser.HasFieldsEnclosedInQuotes = true;и входной файл должен будет заключать поля, содержащие запятые в кавычки, в соответствии со спецификацией CSV - Excel это уже делает.
Кристофер Кинг,

4

Вы можете использовать альтернативные «разделители», такие как «;» или "|" но самым простым может быть просто цитирование, которое поддерживается большинством (приличных) библиотек CSV и большинством приличных электронных таблиц.

Для более на CSV разделителях и в спецификации для стандартного формата для описания разделителей и цитирования видеть этот веб - страницу


4

В случае , если вы на * NIX-системе , имеет доступ к sedи может быть один или несколько нежелательных запятые только в конкретной области вашего CSV, вы можете использовать следующий Однострочник для того , чтобы вложить их в "качестве RFC4180 раздела 2 предлагает:

sed -r 's/([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*)/\1"\2"\3/' inputfile

В зависимости от того, в каком поле могут находиться нежелательные запятые, вам придется изменить / расширить группы захвата регулярного выражения (и подстановки).
В приведенном выше примере четвертое поле (из шести) будет заключено в кавычки.

введите описание изображения здесь

В сочетании с параметром --in-place-option вы можете применить эти изменения непосредственно к файлу.

Чтобы «построить» правильное регулярное выражение, нужно следовать простому принципу:

  1. Для каждого поля в вашем CSV, которое находится перед полем с нежелательной запятой (ями), вы пишете одно [^,]*,и складываете их все вместе в группу захвата.
  2. Для поля, которое содержит нежелательные запятую (ы), которые вы пишете (.*).
  3. Для каждого поля после поля с нежелательной запятой (ями) вы пишете по одному ,.* и складываете их все вместе в группу захвата.

Вот краткий обзор различных возможных регулярных выражений / замен в зависимости от конкретной области. Если не дано, замена есть \1"\2"\3.

([^,]*)(,.*)                     #first field, regex
"\1"\2                           #first field, substitution

(.*,)([^,]*)                     #last field, regex
\1"\2"                           #last field, substitution


([^,]*,)(.*)(,.*,.*,.*)          #second field (out of five fields)
([^,]*,[^,]*,)(.*)(,.*)          #third field (out of four fields)
([^,]*,[^,]*,[^,]*,)(.*)(,.*,.*) #fourth field (out of six fields)

Если вы хотите удалить ненужные запятую (и) sedвместо того, чтобы заключать их в кавычки, обратитесь к этому ответу .


3

Если вы хотите заново изобрести колесо, вам может помочь следующее:

public static IEnumerable<string> SplitCSV(string line)
{
    var s = new StringBuilder();
    bool escaped = false, inQuotes = false;
    foreach (char c in line)
    {
        if (c == ',' && !inQuotes)
        {
            yield return s.ToString();
            s.Clear();
        }
        else if (c == '\\' && !escaped)
        {
            escaped = true;
        }
        else if (c == '"' && !escaped)
        {
            inQuotes = !inQuotes;
        }
        else
        {
            escaped = false;
            s.Append(c);
        }
    }
    yield return s.ToString();
}

3

В Европе у нас эта проблема должна появиться раньше, чем этот вопрос. В Европе мы используем все запятые для десятичной точки. Смотрите эти цифры ниже:

| American      | Europe        |
| ------------- | ------------- |
| 0.5           | 0,5           |
| 3.14159265359 | 3,14159265359 |
| 17.54         | 17,54         |
| 175,186.15    | 175.186,15    |

Поэтому невозможно использовать запятую для файлов CSV. По этой причине файлы CSV в Европе разделяются точкой с запятой ( ;) .

Такие программы, как Microsoft Excel, могут читать файлы с точкой с запятой, и можно переключаться с разделителя. Вы даже можете использовать tab ( \t) в качестве разделителя. Смотрите этот ответ от пользователя Ужина .


2

Если вы заинтересованы в более образовательном упражнении о том, как анализировать файлы в целом (на примере CSV), вы можете прочитать эту статью Джулиана Бакнолла. Мне нравится статья, потому что она разбивает вещи на гораздо более мелкие проблемы, которые гораздо менее непреодолимы. Сначала вы создаете грамматику, и когда у вас есть хорошая грамматика, преобразование грамматики в код является относительно простым и методичным процессом.

Статья использует C # и имеет ссылку внизу для загрузки кода.


1

Вот изящный маленький обходной путь:

Вместо этого вы можете использовать греческий знак нижней цифры (U + 0375)

Похоже, это ͵

Использование этого метода также экономит много ресурсов ...


1

Просто используйте SoftCircuits.CsvParser на NuGet. Он будет обрабатывать все эти детали для вас и эффективно обрабатывает очень большие файлы. И, при необходимости, он может даже импортировать / экспортировать объекты, сопоставляя столбцы со свойствами объекта. Кроме того, мое тестирование показало, что оно в среднем почти в 4 раза быстрее, чем популярный CsvHelper.


0

Поскольку это касается общих практик, давайте начнем с правил большого пальца:

  1. Не используйте CSV, используйте XML с библиотекой для чтения и записи XML-файла.

  2. Если вы должны использовать CSV. Сделайте это правильно и используйте бесплатную библиотеку для анализа и хранения файлов CSV.

Для обоснования 1) большинство синтаксических анализаторов CSV не поддерживают кодирование, поэтому, если вы не имеете дело с US-ASCII, у вас возникнут проблемы. Например, Excel 2002 хранит CSV в локальной кодировке без каких-либо замечаний о кодировке. Стандарт CSV не получил широкого распространения :(. С другой стороны, стандарт XML хорошо принят и хорошо обрабатывает кодировки.

Чтобы оправдать 2), существует множество парсеров csv для почти всех языков, поэтому нет необходимости изобретать колесо, даже если решения выглядят довольно просто.

Чтобы назвать несколько:

  • для Python использовать встроенный модуль CSV

  • для проверки Perl CPAN и Text :: CSV

  • для php используйте встроенные функции fgetcsv / fputcsv

  • для проверки Java библиотеки SuperCVS

На самом деле нет необходимости реализовывать это вручную, если вы не собираетесь анализировать это на встроенном устройстве.


12
XML не всегда ответ. CSV - правильный формат для работы, когда у вас много плотных табличных данных (например, электронных таблиц). Эти теги вносят много накладных расходов, и если каждая строка имеет идентичный формат, нет необходимости явно указывать, что представляет каждое значение. XML отлично подходит, если у вас есть сложные иерархические данные или записи с необязательными полями. Это не всегда так.
Адам Яскевич,

Теоретически, «теги» вносят некоторые накладные расходы, но я не могу придумать ни одного реального приложения, в котором оно может стать проблемой. У вас есть практические примеры? Для работы с данными следует использовать базу данных вместо CSV. Если мы говорим о сериализации данных (резервное копирование, обмен данными), будет ли иметь значение, если анализ занимает неделю вместо 5 дней?
Петр Чапла

2
В основном, любая ситуация, в которой у вас есть данные, которые лучше всего представлены в виде таблицы. Скажем, у вас есть данные от дюжины различных датчиков, которые вы используете часто, и вы записываете метку времени и значение каждого из датчиков в это время. Каждая запись идентична: отметка времени, датчик0, датчик1, ... датчик11. XML отлично подходит для представления сложных, нерегулярных данных, но это довольно тяжелый формат, который не подходит для каждой конкретной ситуации. ПОЦЕЛУЙ
Адам Яскевич

10
Некоторые люди видят проблему, и они говорят: «Я знаю, я буду использовать XML!» Теперь у них две проблемы.
Адам Яскевич,

Я полностью согласен, что xml - это не ответ на все вопросы. Особенно это не подходит как замена базы данных, ни для файлов конфигурации. Но здесь речь шла об обмене данными, для которых был разработан XML.
Петр Чапла

0

Вы можете прочитать файл CSV, как это.

это использует расколы и заботится о пробелах.

ArrayList List = new ArrayList();
static ServerSocket Server;
static Socket socket;
static ArrayList<Object> list = new ArrayList<Object>();


public static void ReadFromXcel() throws FileNotFoundException
{   
    File f = new File("Book.csv");
    Scanner in = new Scanner(f);
    int count  =0;
    String[] date;
    String[] name;
    String[] Temp = new String[10];
    String[] Temp2 = new String[10];
    String[] numbers;
    ArrayList<String[]> List = new ArrayList<String[]>();
    HashMap m = new HashMap();

         in.nextLine();
         date = in.nextLine().split(",");
         name = in.nextLine().split(",");
         numbers = in.nextLine().split(",");
         while(in.hasNext())
         {
             String[] one = in.nextLine().split(",");
             List.add(one);
         }
         int xount = 0;
         //Making sure the lines don't start with a blank
         for(int y = 0; y<= date.length-1; y++)
         {
             if(!date[y].equals(""))
             {   
                 Temp[xount] = date[y];
                 Temp2[xount] = name[y];
                 xount++;
             }
         }

         date = Temp;
         name =Temp2;
         int counter = 0;
         while(counter < List.size())
         {
             String[] list = List.get(counter);
             String sNo = list[0];
             String Surname = list[1];
             String Name = list[2];
             for(int x = 3; x < list.length; x++)
             {           
                 m.put(numbers[x], list[x]);
             }
            Object newOne = new newOne(sNo, Name, Surname, m, false);
             StudentList.add(s);
             System.out.println(s.sNo);
             counter++;
         }

0

Во-первых, давайте спросим себя: «Почему мы чувствуем необходимость обрабатывать запятые по-разному для файлов CSV?»

Для меня ответ таков: «Потому что, когда я экспортирую данные в CSV-файл, запятые в поле исчезают, и мое поле разделяется на несколько полей, где запятые появляются в исходных данных». (Это потому, что запятая является символом разделителя полей CSV.)

В зависимости от вашей ситуации, точки с запятой могут также использоваться в качестве разделителей полей CSV.

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

Итак, вот как вы можете сделать это в Go:

// Replace special CSV characters with single low-9 quotation mark
func Scrub(a interface{}) string {
    s := fmt.Sprint(a)
    s = strings.Replace(s, ",", "‚", -1)
    s = strings.Replace(s, ";", "‚", -1)
    return s
}

Второй символ с запятой в функции замены - десятичное 8218.

Имейте в виду, что если у вас есть клиенты, которые могут иметь программы чтения текста только для ascii, этот символ decima 8218 не будет выглядеть как запятая. Если это ваш случай, я бы рекомендовал окружить поле запятой (или точкой с запятой) двойными кавычками в RFC 4128: https://tools.ietf.org/html/rfc4180


0

Я обычно URL-кодирую поля, которые могут иметь запятые или специальные символы. А затем декодируйте его, когда он используется / отображается на любом визуальном носителе.

(запятые становятся% 2C)

У каждого языка должны быть методы для URL-кодирования и декодирования строк.

например, в Java

URLEncoder.encode(myString,"UTF-8"); //to encode
URLDecoder.decode(myEncodedstring, "UTF-8"); //to decode

Я знаю, что это очень общее решение, и оно не может быть идеальным для ситуации, когда пользователь хочет просмотреть содержимое CSV-файла вручную.


0

Я обычно делаю это в моих процедурах разбора CSV-файлов. Предположим, что переменная 'line' - это одна строка в файле CSV, а все значения столбцов заключены в двойные кавычки. После выполнения следующих двух строк вы получите столбцы CSV в коллекции 'values'.

// The below two lines will split the columns as well as trim the DBOULE QUOTES around values but NOT within them
    string trimmedLine = line.Trim(new char[] { '\"' });
    List<string> values = trimmedLine.Split(new string[] { "\",\"" }, StringSplitOptions.None).ToList();

1
Почему мой код никогда не отображается несколькими цветами в StackOverflow? Я делаю отступ на четыре пробела.
user1451111


0

Самое простое решение, которое я нашел, это то, которое использует LibreOffice:

  1. Заменить все буквальное "на
  2. Положите двойные кавычки вокруг вашей строки

Вы также можете использовать тот, который использует Excel:

  1. Заменить все буквальное "на""
  2. Положите двойные кавычки вокруг вашей строки

Обратите внимание, что другие люди рекомендовали сделать только шаг 2, описанный выше, но это не работает со строками, за "которыми следует a ,, как в CSV, где вы хотите иметь один столбец со строкой hello",world, так как CSV будет читать:

"hello",world"

Который интерпретируется как строка с двумя столбцами: helloиworld"


1
По стандартным правилам любое поле, содержащее либо символ разделения, либо кавычку, окружено кавычками, а любые кавычки внутри, которые удваиваются, так что проблем нет. Ваше hello",worldполе просто необходимо сохранить как "hello"",world", которое можно проанализировать на 100% правильно.
Nyerguds

0
    public static IEnumerable<string> LineSplitter(this string line, char 
         separator, char skip = '"')
    {
        var fieldStart = 0;
        for (var i = 0; i < line.Length; i++)
        {
            if (line[i] == separator)
            {
                yield return line.Substring(fieldStart, i - fieldStart);
                fieldStart = i + 1;
            }
            else if (i == line.Length - 1)
            {
                yield return line.Substring(fieldStart, i - fieldStart + 1);
                fieldStart = i + 1;
            }

            if (line[i] == '"')
                for (i++; i < line.Length && line[i] != skip; i++) { }
        }

        if (line[line.Length - 1] == separator)
        {
            yield return string.Empty;
        }
    }

0

Я использовал библиотеку Csvreader, но с ее помощью я получил данные, взорвавшись от запятой (,) в значении столбца.

Поэтому, если вы хотите вставить данные файла CSV, которые содержат запятую (,) в большинстве значений столбцов, вы можете использовать функцию ниже. Ссылка на автора => https://gist.github.com/jaywilliams/385876

function csv_to_array($filename='', $delimiter=',')
{
    if(!file_exists($filename) || !is_readable($filename))
        return FALSE;

    $header = NULL;
    $data = array();
    if (($handle = fopen($filename, 'r')) !== FALSE)
    {
        while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE)
        {
            if(!$header)
                $header = $row;
            else
                $data[] = array_combine($header, $row);
        }
        fclose($handle);
    }
    return $data;
}

0

Я использовал библиотеку papaParse для анализа файла CSV и получения пар ключ-значение (ключ / заголовок / первая строка значения файла CSV).

Вот пример, который я использую:

https://codesandbox.io/embed/llqmrp96pm

там есть файл dummy.csv для демонстрации разбора CSV.

Я использовал его в ReactionJS, хотя его легко воспроизвести в приложении, написанном на любом языке.


0

Пример может помочь показать, как запятые могут отображаться в CSV-файле. Создайте простой текстовый файл следующим образом:

Сохраните этот текстовый файл как текстовый файл с суффиксом «.csv» и откройте его в Excel 2000 из Windows 10.

aa, bb, cc, d; d "В представлении электронной таблицы нижняя строка должна выглядеть так, как показано выше, за исключением того, что ниже показана отображаемая запятая вместо точки с запятой между точками". аа, bb, cc, "d, d", это работает даже в Excel

аа, bb, cc, "d, d", это работает даже в Excel 2000 аа, bb, cc, "d, d", это работает даже в Excel 2000 аа, bb, cc, "d, d", это работает даже в Excel 2000

aa, bb, cc, "d, d", это терпит неудачу в Excel 2000 из-за пробела в первой цитате aa, bb, cc, "d, d", это терпит неудачу в Excel 2000 из-за пробела после первой цитаты aa, bb, cc, "d, d", это не удается в Excel 2000 из-за пробела в космосе, первая цитата

aa, bb, cc, "d, d", это работает даже в Excel 2000 даже с пробелами до и после 2-й кавычки. aa, bb, cc, "d, d", это работает даже в Excel 2000 даже с пробелами до и после 2-й кавычки. aa, bb, cc, "d, d", это работает даже в Excel 2000 даже с пробелами до и после 2-й кавычки.

Правило: если вы хотите отобразить запятую в ячейке (поле) файла .csv: «начинайте и заканчивайте поле двойными кавычками, но избегайте пробелов перед первой кавычкой»


-1

Я думаю, что самое простое решение этой проблемы состоит в том, чтобы клиент открыл CSV в Excel, а затем Ctrl + R, чтобы заменить все запятые на любой идентификатор, который вы хотите. Это очень просто для клиента и требует только одного изменения в вашем коде, чтобы прочитать выбранный вами разделитель.


Кто сказал, что у них есть Excel? На самом деле, кто говорит, что это даже человек, который делает загрузку? ...
bytedev

-3

Используйте символ табуляции (\ t) для разделения полей.


4
-1 Прекрасно, пока кто-то не использует вкладку в их значении, а затем вы вернетесь к проблеме, которую получил человек, задающий вопрос. Замена одного символа-разделителя на другой не решит проблему.
Бытев

Бред какой то. Люди не могут вводить вкладки при вводе данных. В большинстве форм это просто перемещает точку ввода данных в следующее поле.
Пьер

6
«Люди не могут вводить вкладки при вводе данных» .... Вы серьезно? A) Конечно, человек может поместить вкладку в поле ввода. B) Кто говорит, что это GUI, из которого поступают данные? В) кто говорит, что это даже человек, который вводит данные?
Бытев
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.