Как сохранить извлечение определенных данных из файла CSV без заголовков в Java? - PullRequest
0 голосов
/ 17 февраля 2019

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

Я использую библиотеку fastCSV для разбора файла, однако данные должны быть сохранены, а определенные поля должны быть получены.Поскольку все данные не нужны, я пропускаю каждую третью строку.Есть ли способ установить заголовки после анализа файла и сохранить его в структуре данных, такой как ArrayList?

Вот функция, которая загружает файл:

public void fastCsv(String filePath) { 
    File file = new File(filePath);
    CsvReader csvReader = new CsvReader();
    int linecounter = 1;

    try (CsvParser csvParser = csvReader.parse(file, StandardCharsets.UTF_8)) {
        CsvRow row;
        while ((row = csvParser.nextRow()) != null) {
            if ((linecounter % 3) > 0 ) {
            // System.out.println("Read line: " + row);
            //System.out.println("First column of line: " + row.getField(0));
            System.out.println(row);

            }
        linecounter ++;
        }
        System.out.println("Execution Time in ms: " + elapsedTime);
        csvParser.close();
        } catch (IOException e) {
            e.printStackTrace();
    }
}

Любое понимание будет с благодарностью.

Ответы [ 2 ]

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

univocity-parsers поддерживает выбор полей и может сделать это очень легко.Это также быстрее, чем используемая вами библиотека.

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

Ввод

    String input = "X, X2, Symbol, Date, Open, High, Low, Close, Volume\n" +
            " 5, 9, AAPL, 01-Jan-2015, 110.38, 110.38, 110.38, 110.38, 0\n" +
            " 2710, 289,  AAPL, 01-Jan-2015, 110.38, 110.38, 110.38, 110.38, 0\n" +
            " 5415, 6500, AAPL, 02-Jan-2015, 111.39, 111.44, 107.35, 109.33, 53204600";

Настройка

    CsvParserSettings settings = new CsvParserSettings(); //many options here, check the tutorial
    settings.setHeaderExtractionEnabled(true); //tells the parser to use the first row as the header row
    settings.selectFields("X", "X2"); //selects the fields 

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

    CsvParser parser = new CsvParser(settings);
    for(String[] row : parser.iterate(new StringReader(input))){
        System.out.println(Arrays.toString(row));
    }
}

Вывод

[5, 9]
[2710, 289]
[5415, 6500]

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

Обработайте File в вашем коде, измените приведенный выше пример, чтобы сделать это:

    for(String[] row : parser.iterate(new File(filePath))){
         ... //your logic goes here.
    }

Если вы хотите более полезную запись(с введенными значениями), используйте это вместо:

    for(Record record : parser.iterateRecords(new File(filePath))){
         ... //your logic goes here.
    }

Ускорение

Самый быстрый способ обработки файла через RowProcessor.Это обратный вызов, который получил строки, проанализированные с входных данных:

settings.setProcessor(new AbstractRowProcessor() {
    @Override
    public void rowProcessed(String[] row, ParsingContext context) {
        System.out.println(Arrays.toString(row));
        context.skipLines(3); //use the context object to control the parser
    }
});

CsvParser parser = new CsvParser(settings);
//`parse` doesn't return anything. Rows go to the `rowProcessed` method.
parser.parse(new StringReader(input)); 

Вы должны иметь возможность довольно быстро анализировать очень большие файлы.Если что-то замедляется, посмотрите в своем коде (избегайте добавления значений в списки или коллекции в памяти или, по крайней мере, предварительно выделяйте коллекции хорошего размера и предоставьте JVM большой объем памяти для работы с использованием флагов Xms и Xmx).

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

Надеюсь, это поможет

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

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

Знаете ли вы, какие поля / столбцы вы хотите сохранить, и каким должно быть значение заголовка?, т.е. вам нужны столбцы первого и третьего столбцов и вы хотите, чтобы они назывались «первый» и «третий»?Если это так, вы можете построить HashMap из строки / объектов (или другого подходящего типа, зависит от ваших фактических данных и потребностей) и добавить HashMap к ArrayList - это должно помочь вам, просто убедитесь, чточтобы изменить HashMap типы по мере необходимости

ArrayList<HashMap<String,String>> arr=new ArrayList<>();
HashMap<String,String> hm=new HashMap<>();

while ((row = csvParser.nextRow()) != null) {
    if ((linecounter % 3) > 0 ) {
        // System.out.println("Read line: " + row);
        //System.out.println("First column of line: " + row.getField(0));

        // keep col1 and col3 
        hm.clear();
        hm.put("first",row.getField(0));
        hm.put("third",row.getField(2));
        arr.add(hm);
    }
    linecounter ++;
}

Если вы хотите захватить все столбцы, вы можете использовать аналогичный метод, но я бы построил структуру данных отображения, чтобы вы могли сопоставить индексы полей с столбцамиимена заголовков в цикле для добавления каждого столбца в HashMap, который затем сохраняется в ArrayList

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