상세 컨텐츠

본문 제목

SpringBoot CSV Read / Write (opencsv)

Spring/JAVA

by Chan.94 2024. 9. 12. 16:39

본문

반응형

CSV

CSV(Comma-Separated Values) 파일은 데이터를 저장하기 위해 사용하는 간단한 텍스트 파일 형식이다.

각 데이터 항목을 콤마(,)로 구분하여 한 줄에 하나의 레코드를 저장한다.

주로 데이터를 테이블 형식(행과 열)으로 저장하는 데 사용되며, Excel, 데이터베이스, 스프레드시트 등 다양한 프로그램에서 쉽게 사용할 수 있다.


pom.xml

<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>5.7.1</version>
</dependency>

Write

(1) CSVWriter

 

public void exportCsv1(HttpServletResponse response) throws Exception {
    
    String filename = URLEncoder.encode("UserList.csv", "UTF-8");
    
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/csv; charset=UTF-8");
    response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"");
    
    List<User> list = userRepository.findAll();
    List<String[]> listStrings = new ArrayList<>();
    listStrings.add(new String[]{"ID", "E-mail", "이름", "비밀번호"});
    for (User user: list) {
        String[] rowData = new String[4];
        rowData[0] = String.valueOf(user.getUserId());
        rowData[1] = user.getEmail();
        rowData[2] = user.getUsername();
        rowData[3] = user.getPassword();
        listStrings.add(rowData);
    }
    
    response.getOutputStream().write(0xEF);
    response.getOutputStream().write(0xBB);
    response.getOutputStream().write(0xBF);
    
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8);

    outputStreamWriter.write('\uFEFF');
    
    CSVWriter csvWriter = new CSVWriter(outputStreamWriter);
    csvWriter.writeAll(listStrings);

    csvWriter.close();
    outputStreamWriter.close();
}

 

String filename = URLEncoder.encode("UserList.csv", "UTF-8");
  • File명에 한글이 들어갈 수 있기 때문에 UTF-8로 Encoding
List<User> list = userRepository.findAll();
List<String[]> listStrings = new ArrayList<>();
listStrings.add(new String[]{"ID", "E-mail", "이름", "비밀번호"});
for (User user: list) {
    String[] rowData = new String[4];
    rowData[0] = String.valueOf(user.getUserId());
    rowData[1] = user.getEmail();
    rowData[2] = user.getUsername();
    rowData[3] = user.getPassword();
    listStrings.add(rowData);
}
  • CSV로 저장할 데이터 생성
response.getOutputStream().write(0xEF);
response.getOutputStream().write(0xBB);
response.getOutputStream().write(0xBF);

OutputStreamWriter outputStreamWriter = new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8);
outputStreamWriter.write('\uFEFF');
  • 한글 깨짐현상을 위해 BOM 추가
    BOM을 추가하지 않으면 Excel에서 한글이 깨지는 현상이 나타남

  • 텍스트 편집기에 UTF-8-BOM으로 생성되어야 Excel에서 한글이 깨지지 않는다.
CSVWriter csvWriter = new CSVWriter(outputStreamWriter);
csvWriter.writeAll(listStrings);

csvWriter.close();
outputStreamWriter.close();
  • CSVWriter를 사용하여 CSV파일 생성

(2) StatefulBeanToCsv

public void exportCsv2(HttpServletResponse response) throws Exception {
    
    String filename = URLEncoder.encode("UserList.csv", "UTF-8");
    
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/csv; charset=UTF-8");
    response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + filename + "\"");
    
    response.getOutputStream().write(0xEF);
    response.getOutputStream().write(0xBB);
    response.getOutputStream().write(0xBF);
    
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8);
    outputStreamWriter.write('\uFEFF');
    
    StatefulBeanToCsv<User> beanToCsv = new StatefulBeanToCsvBuilder<User>(outputStreamWriter)
            .withSeparator(CSVWriter.DEFAULT_SEPARATOR)                         
            .withQuotechar(CSVWriter.DEFAULT_QUOTE_CHARACTER)                   
            .withEscapechar(CSVWriter.DEFAULT_ESCAPE_CHARACTER)       
            .build();
    
    beanToCsv.write(userRepository.findAll());
    
    outputStreamWriter.close();
}

 

StatefulBeanToCsv
OpenCSV 라이브러리에서 제공하는 클래스로 객체를 CSV형식으로 변환하여 파일에 저장할 때 사용하며 내부로직에서 CSVWriter를 사용하여 파일을 작성한다.

  • withSeparator
    구분자 설정
  • withQuotechar
    필드 값을 감쌀 때 사용하는 문자 설정
  • withEscapechar
    이스케이프 할 때 사용할 문자 설정
    이스케이프 문자는 특수 문자가 필드 값 내에 포함될 때 이를 올바르게 처리하기 위해 사용

Read

@PostMapping(value = "/read", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<List<String[]>> uploadCsv(@RequestPart MultipartFile file) throws Exception {
    List<String[]> data = new ArrayList<>();
    
    String sOriginalFileName = file.getOriginalFilename();
    String sFileName = FilenameUtils.getBaseName(sOriginalFileName);
    String sExtenstion = FilenameUtils.getExtension(sFileName);
    log.info("originalFilename: {}, filename: {}, extenstion: {}", sOriginalFileName, sFileName, sExtenstion);
    
    if("csv".equals(sExtenstion)) {
        return new ResponseEntity<>(data, HttpStatus.BAD_REQUEST);
    }
    
    try (CSVReader csvReader = new CSVReader(new InputStreamReader(file.getInputStream()))) {
        String[] line;
        while ((line = csvReader.readNext()) != null) {
            data.add(line);
        }
    }
    return new ResponseEntity<>(data, HttpStatus.OK);
}

 

MediaType을 multipart/form-data로 하여 Swagger로 테스트함.

 

CSVReader

try (CSVReader csvReader = new CSVReader(new InputStreamReader(file.getInputStream()))) {
    String[] line;
    while ((line = csvReader.readNext()) != null) {
        data.add(line);
    }
}
  • readNext() : CSV 파일에서 한 줄씩 읽어 배열(String [])로 반환
data = csvReader.readAll();
  • readAll() : CSV 파일의 모든 줄을 한 번에 읽고, 각 줄을 배열로 저장한 리스트(List <String []>)를 반환

readNext(), readAll() 상황에 맞게 사용하면 된다.


CSV 파일 업로드

 

 

반응형

관련글 더보기

댓글 영역

>