2012-04-03 3 views
0

다른 열 유형과 값을 가진 CSV 파일을 구문 분석해야하는 Java 코드를 작성하고 있습니다. 기본 파일은 머리글/열 행없이 다음과 같이 보입니다 (CSV). 파일을 처리 할 때 작업을 단순화하기 위해 열 이름을 사용하여 각 셀의 인덱스 값에 액세스 할 수 있어야합니다. 순간에 CSV 파서를 사용하고 싶지 않습니다. 열거 형은 C++에서와 같이 정수로 다시 변환하지 않기 때문에 CSV를 Java로 파싱 할 때 파일 열 이름과 위치 관리

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

나는, (순서대로) 열 이름의 ArrayList의 사용에 대한 생각했다. 이렇게하면 다음과 같은 것을 할 수 있습니다.

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") ]; 

저는이 기능을 더 잘/현명한 방법으로 사용하고 있습니까? 감사.

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

당신에게 각 라인을 분할 장소 :

+0

예, CSV 파서를 사용하십시오. 이것과 같이 : http://opencsv.sourceforge.net/#javabean-integration – artbristol

답변

1

귀하의 코드가 작동합니다. 당신이 "더 나은"방법을 찾고 있다면 당신은 다시 생각 할 수 있지만 두 지점 :

  1. 같이 IndexOf (객체) 목록의 방법은 너무 빨리하지 않습니다. 비용 O (n). Map<columnNameString, indexNumber>을 유지하고 colName에서 색인을 가져 오는 경우 현재 impl보다 빠를 것입니다. 그 외에도 java에서는 열거 형에서 여러 유형의 값을 얻을 수 있습니다. 당신은 심지어 당신의 enum이 인터페이스를 구현하도록 할 수 있습니다.

  2. 일부 예외 처리를 수행해야합니다. 파일의 한 줄에 (또는 그 이상) 열이없는 경우 어떻게 될까요? 현재 코드가 OutOfbound 예외를 throw합니다. 그러나 이것이 당신의 실제 코드에서 이미 완료 되었기를 바랍니다.

+0

호기심에서 벗어나 언급 했으므로'enum'의 성능은'Map '과 어떻게 비교 될까요? 감사! – sa125

+1

@ sa125 솔직히 말해서, 나는이 두 가지를 비교하는 방법을 모른다. enum은 (당신의 경우에) Columns 타입의 객체이고, Column은 10000 개의 객체/열거 형을 가질 수 있습니다. 반면에 맵 (hashmap 등)은 하나의 값을 얻는 복잡성이 O (1)가 될 것입니다. 그러나 해시를 얻으려면 해시 함수가 뒤에 있어야합니다. 또한 충돌이있을 것입니다. 해시 테이블 구조와 객체를 비교하는 방법 ... 잘 모르겠습니다. – Kent

1

이 문제를 해결하는 가장 쉬운 방법은 다음과 같이 컬렉션 라이브러리를 사용하여 맵의 키 열 이름이 어디에지도의 목록을 만드는 것입니다

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

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 파일에 모든 셀에 액세스 할 수 있습니다 : 배열은 다음 값의 맵을 생성

열 이름은 여전히 ​​값을 얻기 위해) (열거 형 클래스에서 상속 방법을 이름을 사용하여 다음과 같은이

public enum Columns { 
Column1, Column2; 
} 

으로 열거를 확인하고 있습니다 고정하는 경우 :

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

을 그러나이 프로세스를 단순화하기 위해 라이브러리를 사용하기로 결정한 경우 Smooks library 또는 Apache Commons CSV (실제로 가볍습니다!)을 권장 할 수 있습니다.

1

어설 션 중 하나가 정확하지 않습니다. "enum은 C++에서와 같이 정수로 다시 변환되지 않습니다."라고 말하면 사실입니다. 그러나 Java의 Enum은 사실 그보다 유연합니다! 그것들은 객체 일 뿐이며, 숫자가 아닌 많은 수의 값이나 속성을 가질 수 있습니다. 이 (테스트되지 않은) 코드를 고려

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() ];