Разбор CSV в Java - PullRequest
       6

Разбор CSV в Java

6 голосов
/ 11 октября 2010

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

CompanyName,RunDate,10/27/2010,11/12/2010,11/27/2010,12/13/2010,12/27/2010....

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

Ответы [ 9 ]

9 голосов
/ 12 октября 2010

String, split (",") вряд ли будет работать.
Он разделит поля со встроенными запятыми («Foo, Inc.»), даже если они представляют собой одно поле в строке CSV.

Что делать, если название компании:
Компания, ООО
или хуже:
Хорошая, быстрая и дешевая еда Джо


Согласно Википедии: (http://en.wikipedia.org/wiki/Comma-separated_values)

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

   1997,Ford,E350,"Super, luxurious truck"

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

   1997,Ford,E350,"Super ""luxurious"" truck"


Хуже того, в кавычках могут быть вставлены разрывы строк (новые строки; "\ n"):

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

   1997,Ford,E350,"Go get one now  
   they are going fast"



Это демонстрирует проблему с String, split (",") анализом запятых:

CSV линия:

a, b, c, "Company, Inc.", d, e, "Joe's", "Хорошее, быстрое и дешевое", "Еда", f, 10/11 / 2010,1 / 1/2011, g , ч, я


// Test String.split(",") against CSV with
// embedded commas and embedded double-quotes in
// quoted text strings:
//
// Company names are:
//        Company, Inc.
//        Joe's "Good, Fast, and Cheap" Food
//
// Which should be formatted in a CSV file as:
//        "Company, Inc."
//        "Joe's ""Good, Fast, and Cheap"" Food"
//
//
public class TestSplit {
    public static void TestSplit(String s, String splitchar) {
        String[] split_s    = s.split(splitchar);

        for (String seg : split_s) {
            System.out.println(seg);
        }
    }


    public static void main(String[] args) {
        String csvLine = "a,b,c,\"Company, Inc.\", d,"
                            + " e,\"Joe's \"\"Good, Fast,"
                            + " and Cheap\"\" Food\", f,"
                            + " 10/11/2010,1/1/2011, h, i";

        System.out.println("CSV line is:\n" + csvLine + "\n\n");
        TestSplit(csvLine, ",");
    }
}


Производит следующее:


D:\projects\TestSplit>javac TestSplit.java

D:\projects\TestSplit>java  TestSplit
CSV line is:
a,b,c,"Company, Inc.", d, e,"Joe's ""Good, Fast, and Cheap"" Food", f, 10/11/2010,1/1/2011, g, h, i


a
b
c
"Company
 Inc."
 d
 e
"Joe's ""Good
 Fast
 and Cheap"" Food"
 f
 10/11/2010
1/1/2011
 g
 h
 i

D:\projects\TestSplit>



Где эта строка CSV должна быть проанализирована как:


a
b
c
"Company, Inc."
 d
 e
"Joe's ""Good, Fast, and Cheap"" Food"
 f
 10/11/2010
1/1/2011
 g
 h
 i
4 голосов
/ 11 октября 2010

Как другие предложили для разбиения и разбора, вы можете использовать opencsv

Для простых данных, разделите их на "," и проанализируйте их, и используйте Список, чтобы добавить все эти значения.

2 голосов
/ 11 октября 2010

CSV-файл - это \n завершенный файл, в котором каждый столбец может быть разделен:

  • Запятая или
  • Вкладки \t

Я полагаю, что у вас есть BufferedReader, который читает файл CSV и используйте метод readLine() для чтения строки.

Из каждой строки используйте String.split(arg), где arg будет вашей запятойили вкладка \t, чтобы получить массив столбцов .... оттуда вы знаете, что делать.

1 голос
/ 20 ноября 2017

Вы должны действительно попробовать univocity-parsers , так как его анализатор CSV поставляется с множеством функций для обработки всевозможных угловых случаев (неэкранированные кавычки, разделители смешанных строк, файлы в кодировке BOM и т. Д.), Что также является одним из самых быстрых CSV библиотеки вокруг.

Простой пример разбора файла:

CsvParserSettings settings = new CsvParserSettings(); //heaps of options here, check the docs
CsvParser parser = new CsvParser(settings);

//loads everything into memory, simple but can be slow.
List<String[]> allRows = parser.parseAll(new File("/path/to/your.csv"));

//parse iterating over each row
for(String[] row : parser.iterate(new File("/path/to/your.csv"))){
    //process row here
}

//and many other possibilities: Java bean processing, column selection, format detection, etc.

Раскрытие информации: я являюсь автором этой библиотеки. Это с открытым исходным кодом и бесплатно (лицензия Apache V2.0).

1 голос
/ 11 октября 2010

Самая полезная страница на тему разбора CSV, которую я когда-либо нашел, - это:

http://secretgeek.net/csv_trouble.asp

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

1 голос
/ 11 октября 2010

используйте java.util.Scanner - вы можете вызвать useDelimiter (), чтобы сделать запятую вашим разделителем, и читать новые токены с помощью next ().Сканер может быть создан непосредственно из вашего файла или строки, прочитанной из файла.

0 голосов
/ 16 февраля 2019

java.time

Предполагается, что вы используете библиотеку CSV для чтения файла и что вы получаете отдельные значения в виде строк из этой библиотеки:

    String valueFromCsvLibrary = "10/27/2010";
    try {
        LocalDate date = LocalDate.parse(valueFromCsvLibrary, dateFormatter);
        System.out.println("Parsed date: " + date);
    } catch (DateTimeParseException dtpe) {
        System.err.println("Not a valid date: " + dtpe);
    }
Parsed date: 2010-10-27

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

Несмотря на то, что у меня нет опыта, я вполне уверен, что я бы пошел с некоторой библиотекой CSV с открытым исходным кодом.

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

    String lineFromCsvFile = "CompanyName,RunDate,10/27/2010,11/12/2010,11/27/2010,12/13/2010,12/27/2010";
    String[] values = lineFromCsvFile.split(",");
    if (values[1].equals("RunDate")) {
        for (int i = 2; i < values.length; i++) {
            LocalDate date = LocalDate.parse(values[i], dateFormatter);
            System.out.println("Parsed date: " + date);
        }
    }
Parsed date: 2010-10-27
Parsed date: 2010-11-12
Parsed date: 2010-11-27
Parsed date: 2010-12-13
Parsed date: 2010-12-27

Обработка исключений происходит, как и раньше, повторять это не нужно.

0 голосов
/ 11 октября 2010

Чтобы получить каждое значение по одному, используйте StringTokenizer .Создайте его с помощью StringTokenizer(str, ","). (не рекомендуется)

Используйте метод split() класса строки, который загружает все токены в массив.

Используйте класс DateFormat для разбора каждой даты, в частности DateFormat.parse(String).

0 голосов
/ 11 октября 2010

Вы начинаете с чтения всей строки в строку.Затем вы используете функцию String.split (...), чтобы получить все токены в строке, где вы используете разделитель ",".(или это "\", когда вы используете регулярное выражение?)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...