java에서는 엑셀파일을 읽을때 대용량 엑셀 같은 경우에는 메모리 이슈(out of memory)가 발생하는 경우가 많다
그래서 이번에는 대용량 엑셀파일 처리하는 걸 올릴려고 한다.
여기서 부터 실제 코딩
//엑셀파일 읽어서 저장할 List
List<String[]> dataList = null;
OPCPackage opc = null;
opc = OPCPackage.open(file);
XSSFReader xssfReader = null;
xssfReader = new XSSFReader(opc);
XSSFReader.SheetIterator itr = (SheetIterator) xssfReader.getSheetsData();
StylesTable styles = xssfReader.getStylesTable();
ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(opc);
dataList = new ArrayList<String[]>();
while(itr.hasNext()){
InputStream sheetStream = itr.next();
InputSource sheetSource = new InputSource(sheetStream);
//Sheet2ListHandler은 엑셀 data를 가져와서 SheetContentHandler(Interface)를 재정의 해서 만든 Class
//String[] 배열을 몇개 사용할지 숫자
Sheet2ListHandler sheet2ListHandler = new Sheet2ListHandler(dataList, 22); //
ContentHandler handler = new XSSFSheetXMLHandler(styles, strings, sheet2ListHandler, true);
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
SAXParser saxParser = null;;
saxParser = saxFactory.newSAXParser();
//sax parser 방식의 xmlReader를 생성
XMLReader sheetParser = saxParser.getXMLReader();
//xml reader에 row와 cell 이벤트를 생성하는 핸들러를 설정한 후.
sheetParser.setContentHandler(handler);
//위에서 Sheet 별로 생성한 inputSource를 parsing합니다.
//이 과정에서 handler는 row와 cell이벤트를 생성하고 생성된 이벤트는 sheet2ListHandler 가 받아서
처리합니다.
sheetParser.parse(sheetSource);
sheetStream.close();
}
//Sheet2ListHandler
public class Sheet2ListHandler implements SheetContentsHandler {
private boolean firstCellOfRow = false;
private int currentCol = -1;
//collection 객체
private List<String[]> rows;
//collection에 추가될 객체 startRow에서 초기화함
private String[] row;
//collection 내 객체를 String[]로 잡았기 때문에 배열의 길이를 생성시 받도록 설계
private int columnCnt;
//cell 이벤트 처리 시 해당 cell의 데이터가 배열 어디에 저장되야 할지 가리키는 pointer
private int currColNum = 0;
//외부 collection 과 배열 size를 받기 위해 추가한 부분입니다.
public Sheet2ListHandler(List<String[]> rows, int columnsCnt) {
this.rows = rows;
this.columnCnt = columnsCnt;
}
//Row의 시작 부분에서 발생하는 이벤트를 처리하는 method
@Override
public void startRow(int rowNum) {
this.row = new String[columnCnt];
currColNum = 0;
}
//Row의 끝에서 발생하는 이벤트를 처리하는 method
@Override
public void endRow(int rowNum) {
//cell 이벤트에서 담아놓은 row String[]를 collection에 추가
//데이터가 하나도 없는 row는 collection 추가하지 않도록 조건 추가
boolean addFlag = false;
for(String data:row){
if(!"".equals(data)){
addFlag = true;
}
}
if(addFlag)rows.add(row);
}
//cell 이벤트 발생 시 해당 cell의 주소와 값을 받아옴.
@Override
public void cell(String cellReference, String formattedValue, XSSFComment comment) {
// 엑셀 내용중 비어있는 셀은 제외하고 쓰여지기 때문에 아래와 같이 체크후 빈셀은 ""로 채워서 자리를 채워줌
int thisCol = (new CellReference(cellReference)).getCol();
int missedCols = thisCol - currentCol - 1;
for (int i=0; i<missedCols; i++) {
row[currColNum++] = "";
}
currentCol = thisCol;
row[currColNum++] = formattedValue == null ? "":formattedValue;
}
@Override
public void headerFooter(String text, boolean isHeader, String tagName) {
}
'Java' 카테고리의 다른 글
JAVA SPRING + MYBATIS + ORACLE TXT 파일 BLOB 형태로 DB에 INSERT (0) | 2016.11.01 |
---|---|
java 배열 내 문자열 확인 (0) | 2016.10.04 |
[Tomcat] UTF-8 한글 처리 (0) | 2016.04.08 |
이클립스 jdk 경로 지정 (0) | 2016.04.07 |
이클립스 SVN 설치 (0) | 2013.07.24 |