CSV (
comma-separated values
)는 ,(콤마)로 구분되 있는 데이터파일
엑셀로 열어볼 수는 있으나 정보를 엑셀로 막 수정하다가는 파일 전체가 깨질수도 있으니
엑셀로는 읽기만 하는걸 권장
보통 DB에서 csv로 추출한 정보를 가공할때 쓰거나, 데이터를 분석할때등 많이 쓰임
[예시 데이터] (출처: data.go.kr)
// 전라남도 메뉴정보
//
https://www.data.go.kr/data/15076624/fileData.do
// 전라남도 식당 정보
//
https://www.data.go.kr/data/15076621/fileData.do
// path : 파일경로,
// charset : 문자열 인코딩
public static List<LineInfo> makeCSVList(String path, String charset) {
List<LineInfo> list = new ArrayList<>();
try (FileReader fr = new FileReader(path, Charset.forName(charset));
BufferedReader br = new BufferedReader(fr); ) {
String headerStr = br.readLine();
List<String> headerList = csvLineToList(headerStr);
String str = null;
while((str = br.readLine()) != null) {
List<String> infoList = csvLineToList(str);
if(infoList == null) {
continue;
LineInfo info = new LineInfo(headerList, infoList);
list.add(info);
} catch (Exception e) {
e.printStackTrace();
return list;
// headerStr : 메뉴ID,식당ID,메뉴명,메뉴가격,메뉴태그정보,등록일시
// line : 1,858991,짜장면,6000,"주재료 : 돼지고기,야채,면,밀가루 / 조리법 : 볶음 / 소스 : 춘장",2020-10-26 16:45
private static List<String> csvLineToList(String csvLine) {
try {
String delemeter = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)";
List<String> list = new ArrayList<>();
String[] array = csvLine.split(delemeter);
for(String str : array) {
if(str.contains("메뉴ID")) {
str = str.substring(1,str.length());
str = str.replace("\"", "").strip();
list.add(str);
return list;
} catch (Exception e) {
System.err.println("csvLine : " + csvLine);
e.printStackTrace();
return null;
[LineInfo.java]
파일 읽기
package ex03.csv;
import java.util.List;
public class LineInfo {
private List<String> header; // 컬럼값
private List<String> info; // 데이터값
public List<String> getHeader() {
return header;
public void setHeader(List<String> header) {
this.header = header;
public List<String> getInfo() {
return info;
public void setInfo(List<String> info) {
this.info = info;
public LineInfo() {
super();
public LineInfo(List<String> header, List<String> info) {
super();
this.header = header;
this.info = info;
@Override
public String toString() {
StringBuilder sb = new StringBuilder(); // 자추 출력할 예정, 성능 생각해서 StringBuilder로 만들기 StringBuffer도 되긴하는데 빌더가 좀더 빠르다
for(int i=0; i< header.size(); i++) {
sb.append(header.get(i) + ":" + info.get(i) + ", ");
return sb.toString();
public String getData(String header) {
int index = header.indexOf(header);
if(index != -1) {
return info.get(index);
} else {
return null;
public int getSize() {
return header.size();
[RunMain.java]
package ex03.csv;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// 전라남도 메뉴정보
// https://www.data.go.kr/data/15076624/fileData.do
// 전라남도 식당 정보
// https://www.data.go.kr/data/15076621/fileData.do
// 1. 식당과 모든 메뉴를 탐색할수 있는 기능
// 2. 식당을 찾으면 메뉴까지 보여주는 기능
// 3. 메뉴의 키워드를 조회하면 식당 정보가 같이 나올수 있는 기능
public class RunMain {
public static void main(String[] args) {
List<LineInfo> menuList = CSVParser.makeCSVList("전라남도_메뉴정보_20210120.csv", "UTF-8");
System.out.println("메뉴정보 출력");
// menuList.forEach((v) -> System.out.println(v));
System.out.println("--------------------------------------------");
List<LineInfo> restaurantList = CSVParser.makeCSVList("전라남도_식당정보_20201229.csv", "EUC-KR");
System.out.println("식당 정보 출력");
// restaurantList.forEach((v) -> System.out.println(v));
System.out.println("--------------------------------------------");
System.out.println("menuList size : " + menuList.size());
System.out.println("restaurantList size : " + restaurantList.size());
// 1. 식당과 모든 메뉴를 탐색할수 있는 기능
// 1.1 ) 무지성 접근 -> 결론 느리다!
// for(LineInfo info : restaurantList) {
// String rId = info.getData("식당ID");
// for(LineInfo minfo : menuList) {
// if(minfo.getData("식당ID").equals(rId)) {
// System.out.println(minfo);
// }
// }
// System.out.println("------------------------------------------------------");
//// System.out.println(rId);
// }
// 1.2 빠른 접근 방법
// -> map으로 자료구조 구성 필요!
// 식당ID - 식당 Line 정보
Map<String, LineInfo> restaurantIDToLineInfoMap
= new HashMap<String, LineInfo>();
// 식당ID - 메뉴 리스트
Map<String, List<LineInfo>> restaurantIDToMenuListMap
= new HashMap<String, List<LineInfo>>();
// 초기화 코드!
// 순서 존재, 식당-식당 List를 먼저 구성하고 메뉴 리스트를 구성해야함
for(LineInfo info : restaurantList) {
restaurantIDToLineInfoMap.put(info.getData("식당ID"), info);
for(LineInfo info : menuList) {
String rId = info.getData("식당ID");
List<LineInfo> list = restaurantIDToMenuListMap.get(rId);
if(list == null) {
list = new ArrayList<>();
restaurantIDToMenuListMap.put(rId, list);
list.add(info);
// restaurantIDToLineInfoMap.forEach((k,v) -> System.out.println(k+" : "+v));
// restaurantIDToMenuListMap.forEach((k,v) -> System.out.println(k+" : "+v));
// 출력부
for(LineInfo info : restaurantList) {
String rid = info.getData("식당ID");
System.out.println(info);
List<LineInfo> list = restaurantIDToMenuListMap.get(rid);
for(LineInfo info2 : list) {
System.out.println(info2);
System.out.println("-------------------------------------------");
System.out.println("------------------------------------------------------------");
// 2. 식당을 찾으면 메뉴까지 보여주는 기능
String keyword = "오리";
for(LineInfo info : restaurantList) {
if(info.getData("식당명").contains(keyword)) {
System.out.println("==========================================================");
System.out.println(info);
String rid = info.getData("식당ID");
List<LineInfo> list = restaurantIDToMenuListMap.get(rid);
for(LineInfo info2 : list) {
System.out.println(info2);
System.out.println("==========================================================");
System.out.println("------------------------------------------------------------");
// 3. 메뉴의 키워드를 조회하면 식당 정보가 같이 나올수 있는 기능
String keyword2 = "닭갈비";
for(LineInfo info : menuList) {
if(info.getData("메뉴명").contains(keyword2)) {
System.out.println("*********************************************************");
System.out.println(info);
String rid = info.getData("식당ID");
LineInfo info2 = restaurantIDToLineInfoMap.get(rid);
System.out.println(info2);
System.out.println("*********************************************************");