Search

2015년 11월 5일 목요일

[JAVA] [Library] OpenCSV를 이용한 CSV 파일 파싱, 변환.

* CSV 파일은 쉼표로 구분된 파일을 말한다. 그런데, 때에 따라서 쉼표를 '|' 와 같은 형태로 구분해야 한다던가 하는 일도 생기기 마련이다.
* 그 때 유용한 것이 OpenCSV라는 JAVA라이브러리이다.
* 다운로드는 아래의 소스포지 사이트에서 받을 수 있으며, 본 블로그에서는 opencsv-3.5.jar 버젼을 사용했다.

http://sourceforge.net/projects/opencsv/


* 먼저, 아래와 같이 openCSV 라는 자바 프로젝트를 만들고, openCSV라는 패키지 안에
읽기에 필요한 클래스(CSVRead),
쓰기에 필요한 클래스(CSVWrite),
조작을 위한 메인 클래스(Driver)를 만들었다.
* 다음으로, lib 폴더에는 다운받은 jar파일을 넣어서 Build Path에 추가했고,
input 폴더와 output 폴더를 만들었고(정리정돈을 위해..),
input 폴더에는 테스트를 위한 csv파일 하나를 미리 넣어두었다.




















* CSVRead 클래스의 소스

package openCSV;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import com.opencsv.CSVReader;

public class CSVRead {

  private String filename = "input\\test.csv";

  public CSVRead() {}

  public List<String[]> readCsv() {

    List<String[]> data = new ArrayList<String[]>();

    try {
      // CSVReader reader = new CSVReader(new FileReader(filename), '\t');
      // UTF-8
      CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream(filename), "UTF-8"));
      String[] s;

      while ((s = reader.readNext()) != null) {
        data.add(s);
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return data;
  }
}

* CSVWrite 클래스의 소스

package openCSV;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import com.opencsv.CSVWriter;

public class CSVWrite {

  private String filename = "output\\test.txt";

  public CSVWrite() {}

  public void writeCsv(List data) {
    try {
      CSVWriter cw = new CSVWriter(new FileWriter(filename), '|', CSVWriter.NO_QUOTE_CHARACTER);
      Iterator it = data.iterator();
      try {
        while (it.hasNext()) {
          String[] s = (String[]) it.next();
          cw.writeNext(s);
        }
      } finally {
        cw.close();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}


* Driver 클래스의 소스

package openCSV;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Driver {

  public static void main(String[] args) {

    List<String[]> data = new ArrayList<String[]>();
    CSVRead read = new CSVRead();
    data = read.readCsv();
    Iterator<String[]> it = data.iterator();

    while (it.hasNext()) {
      String[] array = (String[]) it.next();
      for (String s : array) {
        System.out.print(s + " ");
      }
      System.out.print("\n");
    }

    // 이곳은 데이터를 파일로 쓰기 위한 코드     CSVWrite cw = new CSVWrite();     cw.writeCsv(data);   } }

* 단순히 CSV파일을 읽기만 하려면, Driver 클래스에서 주석을 달아둔 부분 아래를 생략하고 실행하면 된다.


댓글 5개:

  1. // CSVReader reader = new CSVReader(new FileReader(filename), '\t');
    // UTF-8
    CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream(filename), "UTF-8"));

    한글 깨짐 현상으로 위의 소스를 주석 처리하고 3번째 Line 을 사용하신거 같은데요..
    3번째 라인의 소스로 seperator 를 구분할 수 있을까요?

    답글삭제
    답글
    1. 네, 아래 주석처리 하지 않은 코드로도 충분히 구현 가능합니다.
      사실 윗줄을 응용하실 분들을 위해 저렇게 남겨두었는데요, 예를 들어 탭으로 분리된 tsv 파일이 있다고 가정한다면
      seperator를 아래와 같이 주시면 됩니다.

      CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream(filename), "UTF-8"), '\t');

      삭제
  2. 안녕하세요 질문좀 할려고 합니다
    Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang3/ObjectUtils
    at com.opencsv.CSVParser.(CSVParser.java:209)
    at com.opencsv.CSVReader.(CSVReader.java:201)
    at com.opencsv.CSVReader.(CSVReader.java:183)
    at com.opencsv.CSVReader.(CSVReader.java:135)
    at com.opencsv.CSVReader.(CSVReader.java:75)
    at openCSV.CSVRead.readCsv(CSVRead.java:23)
    at openCSV.Driver.main(Driver.java:12)
    Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.ObjectUtils
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 7 more
    이렇게 뜨는게 뭐가 문제인지 모르겠습니다 코드는 그대로 작성하였구요

    답글삭제
    답글
    1. 안녕하세요, 댓글을 늦게 발견했네요.
      아마도 라이브러리를 build path에 추가하지 않아서 나타나는 문제로 보이긴 합니다만..
      혹이라도 아닐 경우, 사용하신 라이브러리와 코드 등을 캡쳐해서 제 메일로 보내주시면 한 번 봐드릴께요 ^^

      삭제
  3. 우아 덕분에 인코딩할 수 있었어요~~ 감사합니답!!

    답글삭제