네로개발일기

개발자 네로의 개발 일기, 자바를 좋아합니다 !

반응형

 

[ 이전 글 ] Apache POI를 이용한 엑셀 파일 읽기

https://frogand.tistory.com/126

 

[Spring] Apache POI 를 이용한 엑셀 파일 읽기

[Spring] Apache POI 를 이용한 엑셀 파일 읽기 ✨ 의존성 - Spring Boot - Spring Web - Thymeleaf - Lombok 1. Apache POI , Tika 관련 의존성 추가 maven일 경우 pom.xml org.apache.poi poi 4.1.2 org...

frogand.tistory.com

 

 문제 상황 

POI 라이브러리를 사용해서 Excel 작업을 진행 중이었다.

근데 Excel 용량이 커서인지 진행이 되지 않았음. 계속 뜨는 오류 메시지는 

java.lang.OutOfMemoryError: Java heap space

[삽질 1] Exceed Java Heap Size 

Xmx를 늘려주었다.. 4096M 까지.. (사실 얼마나 늘려야할지 몰랐는데, 아무튼 이게 문제가 아니라는 것을 깨달음)

- 참고: Xmx 옵션은 자바 힙 사이즈의 최대를 결정해주는 옵션이다. 

- 참고: 엑셀 파일의 크기는 58M에서 87M였다.

 

그래도 되지 않았다.

 

[삽질 2] Thread Starvation

HikariPool-1 - Thread starvation or clock leap detected

thread 사용하지도 않았는데 갑자기 Thread starvation,, => Multi-Threaded JDBCTemplate 사용해봤지만

역시나 되지 않았다.

 

[삽질 3] SXSSFWorkbook

=> XSSFWorkbook를 생성하는 시점부터 문제가 생기는 것을 알고,  XSSFWorkbook에 문제가 있을 것 같다는 생각과 함께...

Workbook workbook = new XSSFWorkbook(file.getInputStream());

SXSSFWorkbook 방식이 있다는 것을 알았지만, Write Only로 엑셀 파일을 만들 때만 사용할 수 있다. 

엑셀 파일 읽기에는 사용이 불가능했다.

 

 

 해결 방안 

=> SAX를 이용하여 Excel 파일 읽기

* pom.xml에 의존성을 추가

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId> <!-- 엑셀 2007 이상 버전에서 사용 -->
    <version>4.1.2</version>
</dependency>
<dependency>
    <groupId>sax</groupId>
    <artifactId>sax</artifactId>
    <version>2.0.1</version>
</dependency>

ExcelSheetHandler.java

import org.apache.poi.ooxml.util.SAXHelper;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.xml.sax.ContentHandler;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;

import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

public class ExcelSheetHandler implements XSSFSheetXMLHandler.SheetContentsHandler {

    private int currentCol = -1;
    private int currRowNum = 0;

    private List<List<String>> rows = new ArrayList<List<String>>();    //실제 엑셀을 파싱해서 담아지는 데이터
    private List<String> row = new ArrayList<String>();
    private List<String> header = new ArrayList<String>();

    public static ExcelSheetHandler readExcel(File file) throws Exception {

        ExcelSheetHandler sheetHandler = new ExcelSheetHandler();
        try {

            OPCPackage opc = OPCPackage.open(file);
            XSSFReader xssfReader = new XSSFReader(opc);
            StylesTable styles = xssfReader.getStylesTable();
            ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(opc);

            //엑셀의 시트를 하나만 가져오기.
            //여러개일경우 iter문으로 추출해야 함. (iter문으로)
            InputStream inputStream = xssfReader.getSheetsData().next();
            InputSource inputSource = new InputSource(inputStream);
            ContentHandler handle = new XSSFSheetXMLHandler(styles, strings, sheetHandler, false);

            XMLReader xmlReader = SAXHelper.newXMLReader();
            xmlReader.setContentHandler(handle);
            
            xmlReader.parse(inputSource);
            inputStream.close();
            opc.close();
        } catch (Exception e) {
            //에러 발생했을때
        }

        return sheetHandler;

    }

    public List<List<String>> getRows() {
        return rows;
    }

    @Override
    public void startRow(int arg0) {
        this.currentCol = -1;
        this.currRowNum = arg0;
    }

    @Override
    public void cell(String columnName, String value, XSSFComment var3) {
        int iCol = (new CellReference(columnName)).getCol();
        int emptyCol = iCol - currentCol - 1;

        for (int i = 0; i < emptyCol; i++) {
            row.add("");
        }
        currentCol = iCol;
        row.add(value);
    }

    @Override
    public void headerFooter(String arg0, boolean arg1, String arg2) {
        //사용 X
    }

    @Override
    public void endRow(int rowNum) {
        if (rowNum == 0) {
            header = new ArrayList(row);
        } else {
            if (row.size() < header.size()) {
                for (int i = row.size(); i < header.size(); i++) {
                    row.add("");
                }
            }
            rows.add(new ArrayList(row));
        }
        row.clear();
    }

    public void hyperlinkCell(String arg0, String arg1, String arg2, String arg3, XSSFComment arg4) {
        // TODO Auto-generated method stub

    }
}

 

아래는 위 ExcelSheetHandler를 사용하는 방법이다.

// 엑셀 데이터 양식 example
/*    A열				B열
1행   nero@nate.com		Seoul
2행   jijeon@gmail.com	Busan
3행   jy.jeon@naver.com	Jeju
*/

String filePath = "/Users/jyjeon/Downloads/정의서/복사본.xlsx";
File file = new File(filePath);

ExcelSheetHandler excelSheetHandler = ExcelSheetHandler.readExcel(file);

// excelDatas >>> [[nero@nate.com, Seoul], [jijeon@gmail.com, Busan], [jy.jeon@naver.com, Jeju]]
List<List<String>> excelDatas = excelSheetHandler.getRows();

for(List<String> dataRow : excelDatas) // row 하나를 읽어온다.
    for(String str : dataRow){ // cell 하나를 읽어온다.
        System.out.println(str);
    }
}

 

 

출처

https://poi.apache.org/components/spreadsheet/how-to.html#xssf_sax_api

 

The New Halloween Document

<!--+ |breadtrail +--> <!--+ |start Menu, mainarea +--> <!--+ |start Menu +--> <!--+ |end Menu +--> <!--+ |start content +--> The New Halloween Document How to use the HSSF API Capabilities This release of the how-to outlines functionality for the current

poi.apache.org

https://m.blog.naver.com/hyoun1202/220245067954

 

[JAVA] Apache POI를 사용한 Excel 파일 읽기(대용량 Excel 파일 읽기 포함)

Apache POI를 사용해서 Excel 파일을 읽어들이는 방법에는 4가지 방법이 있다. 1번째 방법 - FileIn...

blog.naver.com

https://hoonzi-text.tistory.com/29

 

java excel read 문제 해결 (XSSFWorkbook heap space OOM)

이전 포스트 했던 excel 관련해 발생한 문제가 있어 정리 해보려고 한다. java excel 처리 정리 java excel 처리 정리 매번 엑셀을 java로 읽을때마다 찾아보는게 귀찮아서 정리한다. 사용 모듈 apache poi

hoonzi-text.tistory.com

 

728x90
반응형
blog image

Written by ner.o

개발자 네로의 개발 일기, 자바를 좋아합니다 !