2012-04-03 1 views
0

Я пишу код Java, который должен анализировать файлы csv с разными типами столбцов и значениями. Основной файл выглядит примерно так (CSV), без строки заголовка/столбца. Чтобы упростить процесс обработки файла, я хочу иметь доступ к значению индекса каждой ячейки, используя имя столбца. Я не хочу использовать парсер CSV на данный момент.Управление именами столбцов и позициями при анализе CSV с помощью Java

Column1 | Column2 | Column3 |... 
    --------+---------+---------+--- 
    val10 | val20 | val30 | 
    val11 | val21 | val31 | 
    val12 | val22 | val32 | 
    ...  | ...  | ...  | 

Я думал об использовании ArrayList имен столбцов (в порядке), так как перечисление не конвертировать обратно в целые числа, как и в C++. Таким образом, я мог бы сделать что-то вроде:

ArrayList<String> columnNames = new ArrayList<String>(); 
    columnNames.add("Column1"); 
    columnNames.add("Column2"); 
    columnNames.add("Column3"); 

    // read each line from the file ... 
    String[] row = line.trim().split(","); 
    String col2 = row[ columnNames.indexOf("Column2") ]; 

Я довольно новыми для Java - там лучше/умнее способ сделать это? Благодарю.

+0

Да, используйте парсер CSV. Как и этот: http://opencsv.sourceforge.net/#javabean-integration – artbristol

ответ

1

Ваш код работает. однако две точки вы можете хотеть повторно думать, если вы ищете «лучше» способ:

  1. IndexOf (объект) метод List не так быстро. стоит O (n). если вы поддерживаете Map<columnNameString, indexNumber> и получаете индекс от colName, он должен быть быстрее, чем ваш текущий имп. Кроме того, в java вы можете получить различные типы значений из перечисления. вы даже можете позволить своим интерфейсам реализовать enum.

  2. Вы должны выполнить обработку исключений. что если одна строка в вашем файле отсутствует (или больше) столбцов. Ваши текущие коды будут вызывать исключение OutOfbound. однако я надеюсь, что это уже было сделано в ваших реальных кодах.

+0

Просто из любопытства и с тех пор, как вы упомянули об этом - как производительность 'enum' сравнивается с использованием 'Map '? Благодаря! – sa125

+1

@ sa125, честно говоря, я не знаю, как сравнить эти два. enum - объект типа Columns (в вашем случае), а Column может иметь 10000 объектов/перечислений. с другой стороны, map, (hashmap, например), сложность получения одного значения будет O (1). однако есть функции hash, чтобы получить хэш. также были бы столкновения. как сравнить структуру хэш-таблицы и объект ... Я не знаю. – Kent

1

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

List<Map<String,String>> records = someCodeForReadingDataFromFile(); 

Где вы разделите каждую строку, чтобы массив, а затем создать карту значений:

List<Map<String,String>> someCodeForReadingDataFromFile() { 
    List<<Map<String,String>> rowsList = new LinkedList<<Map<String,String>>(); 
    final String[] columnNames = {"Column1", "Column2", "Column3"}; 

    // add some loop to read one line at the time from the file 
    ... 
    String[] rows = line.trim().split(","); 
    Map<String, String> rowMap = new HashMap<String, String>(); 
    for(int columnIndex = 0; columnIndex < columnNames.length; columnIndex++) { 
    rowMap.put(columnNames[columnIndex], rows[columnIndex]); 
    } 
    rowsList.add(rowMap); 
    // repeat this until you reach EOF 
    return rowsList; 
} 

затем вы можете получить доступ ко всем клеткам в CSV файл их индекс строки и имя столбца:

String valueOne = records.get(0).get("Column1"); // will set the value to "val10" 

Если имена столбцов фиксированы вы можете сделать перечисление таких, как этого

public enum Columns { 
Column1, Column2; 
} 

И затем использовать имя() метод, унаследованный от класса Enum, чтобы получить значение:

String valueOne = records.get(0).get(Columns.Column1); 

Однако, если вы решите использовать библиотеку для упрощения этого процесса, я могу действительно рекомендовать Smooks library или даже Apache Commons CSV (действительно легкий!).

1

Одно из ваших утверждений неточно. Вы указываете, что «перечисление не преобразуется обратно в целые числа, как в C++», что верно. Однако, перечисления в Java на самом деле более гибкие, чем это! Это объекты, которые могут иметь любое количество значений или свойств, а не просто число. Рассмотрим это (непроверенные) код:

public enum ColumnEnum { 
    COL1(1), 
    COL2(2), 
    COL3(3); 

    private final int index; 
    ColumnEnum(int index) { 
     this.index = index; 
    } 
    public double index() { return index; } 
} 

Теперь вы можете обратиться к частям массива, как это:

// read each line from the file ...    
String[] row = line.trim().split(",");    
String col2 = row[ ColumnEnum.COL1.index() ];  
Смежные вопросы