IT 잇뽀잇뽀

[Java] CSV 파일 읽어서 데이터 가공하기(CSVReader) 본문

IT/Java

[Java] CSV 파일 읽어서 데이터 가공하기(CSVReader)

뜽뇽이 2019. 8. 9. 18:02
Intro

 

CSV 파일을 읽어서 데이터 구조를 변경하는 가공업무가 생겼다.
가공 전 데이터와 가공 후 데이터는 아래와 같다.

[가공 전 데이터 Sample]

no col1 col2 col3 col4 col5 col6 Answer
1 data1 data2 data3 data4 data5 data6 1|2|4|6
2 data7 data8 data9 data10 data11   4

[가공 후 데이터 Sample]

new_no col Answer no
1 data1 Y 1
2 data2 Y 1
3 data3 N 1
4 data4 Y 1
5 data5 N 1
6 data6 Y 1
7 data7 N 2
8 data8 N 2
9 data9 N 2
10 data10 Y 2
11 data11 N 2

col1~col6까지의 데이터를 세로로 적재하는 작업인데. 2가지 중요한 점이 있다.

  • Answer 컬럼을 참고하여, 각 숫자에 해당하는 컬럼 데이터는 Y로 대체하고, 그 외에는 N를 입력할 것.
  • col1~col6에 값이 있는 데이터만 쌓을 것이며(없는 col은 pass) 해당 컬럼의 no값을 넣어줄 것.

이를 수행하기 위해 JAVA IO 코드를 작성해봤다.

 

Source Code

 

Class는 IO가 수행되는 main 코드와 IO 데이터를 담을 VO 코드로 총 2개.
CSV를 일기 위해 사용한 라이브러리는 CSVReader이다.

CSVReader는 CSV 파일을 한 줄씩 읽어서 String 배열로 리턴하는 메소드를 가지고 있다. 이를 고려하여 코드를 작성해봤다.

ChoiceProcessing.java
package dataset.question_choice;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import com.opencsv.CSVReader;

public class ChoiceProcessing {
	
	private static int nocount=1;
	
	private static List<String> ContentsList(String [] line){
		
		List<String> contents_list;
		
		// contents list 구축
		contents_list = new ArrayList<String>();
		
		for(int i=1; i<7; i++) {
			if(!line[i].equals("")) {
				if(line[i].contains(",")){
					line[i] = line[i].replace(',', '@');	// CSV 작업을 위해 ,를 @로 변환.
					contents_list.add(line[i]);
				} else {
					contents_list.add(line[i]);
				}
			} else {
				continue;
			}
		}
		
		return contents_list;
	}
	
	private static List<Integer> AnswerList(String [] line){
		
		List<Integer> answer_list;
		StringTokenizer st;
		
		// answer list 구축
		answer_list = new ArrayList<Integer>();
		st = new StringTokenizer(line[7], "|");
		
		while(st.hasMoreTokens()) {
			answer_list.add(Integer.parseInt(st.nextToken()));
		}
		
		return answer_list;
		
	}
	
	private static void FileWrite(List<String> contents_list, List<Integer> answer_list, String [] line) throws IOException {
		
		ChoiceVo vo;
		File f;
		FileWriter fw;
		BufferedWriter bw;
		OutputStreamWriter osw;
		FileOutputStream fos;
		String path = "result.csv";
		
		for(int i=0; i<contents_list.size(); i++) {
			
			// Vo input
			vo = new ChoiceVo();
			
			vo.setNo(nocount);
			vo.setContents(contents_list.get(i));
			if(answer_list.contains(i+1)) {
				vo.setAnswer("Y");
			} else {
				vo.setAnswer("N");
			}
			vo.setQno(Integer.parseInt(line[0]));
			nocount++;
			
			System.out.println(vo);
			
			// File write
			f = new File(path);
			fw = new FileWriter(f, true);
			fw.write(vo.toString()+"\n");
			
			fw.close();
			
		}
	}
	
	public static void main(String[] args) throws Exception {
		
		// Input CSV col = 문항번호	보기문항	정답
		String file = "data.csv";
		String [] line;
		CSVReader reader = new CSVReader(new FileReader(file));
		
		// Row input
		while((line = reader.readNext()) != null ) {
			
			System.out.println("===== START =====");
			
			// contents list 구축
			List<String> contents_list = ContentsList(line);
			
			// answer list 구축
			List<Integer> answer_list = AnswerList(line);
			
			// VO input + File write
			FileWrite(contents_list, answer_list, line);
			
			System.out.println("===== END =====");
		}
	}
}
ChoiceVo.java
package dataset.question_choice;

public class ChoiceVo {

	private int no;
	private String contents;
	private String answer;
	private int qno;

	public ChoiceVo() {
		super();
	}

	public ChoiceVo(int no, String contents, String answer, int qno) {
		super();
		this.no = no;
		this.contents = contents;
		this.answer = answer;
		this.qno = qno;
	}

	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public String getContents() {
		return contents;
	}

	public void setContents(String contents) {
		this.contents = contents;
	}

	public String getAnswer() {
		return answer;
	}

	public void setAnswer(String answer) {
		this.answer = answer;
	}

	public int getQno() {
		return qno;
	}

	public void setQno(int qno) {
		this.qno = qno;
	}

	@Override
	public String toString() {
		
		String str = no+","+contents+","+answer+","+qno;
		
		return str;
		
	}
	
}

단발성 작업이기 때문에 Exception 처리를 Main 메소드에서 처리했다.

CSV 파일을 한줄씩 읽는 While문 안에서 col1~6과 Answer를 각각 List 객체에 넣은 뒤, col1~6을 담은 List 객체를 for문 돌려 VO 객체에 저장하여 VO를 새로운 CSV 파일에 쓰는 코드이다.

		for(int i=1; i<7; i++) {
			if(!line[i].equals("")) {
				if(line[i].contains(",")){
					line[i] = line[i].replace(',', '@');	// CSV 작업을 위해 ,를 @로 변환.
					contents_list.add(line[i]);
				} else {
					contents_list.add(line[i]);
				}
			} else {
				continue;
			}
		}

코드에서 at(@)이 들어간 이유는 col1~6의 내용 중 콤마(,)가 들어간 data가 있었으며, CSV는 콤마(,)로 컬럼을 구분하기 때문에 콤마(,)를 at(@)으로 대체한 것이다.  그 외에 공백일 경우는 continue 처리하여 List 객체에 넣지 않도록했다.

'IT > Java' 카테고리의 다른 글

JSON Simple을 활용한 JSON 문서 parse  (0) 2019.10.04