문제

Java를 사용하여 프로그램적으로 Excel (.XLS MS Excel 2003 형식) 파일에 편지를 쓰려고합니다. Excel 출력 파일에는 ~ 200,000 행이 포함되어 있으며 시트 수 (Excel 한계로 인해 시트 당 64k 행)를 분할하려고합니다.

Apache POI API를 사용해 보았지만 API 객체 모델로 인해 메모리 돼지 인 것 같습니다. 메모리의 통합 문서 개체에 셀/시트를 추가해야하며 모든 데이터가 추가되면 통합 문서를 파일에 쓸 수 있습니다! 다음은 Apache가 API를 사용하여 Excel 파일을 작성하는 방법에 대한 샘플입니다.

Workbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet("new sheet");

//Create a row and put some cells in it
Row row = sheet.createRow((short)0);

// Create a cell and put a value in it.
Cell cell = row.createCell(0);
cell.setCellValue(1);

// Write the output to a file
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();

분명히, ~ 20k 행 (각 행에 10-20 개의 열이 있음)을 작성하면 끔찍한 "java.lang.outofmemoryerRor : java 힙 스페이스"를 제공합니다.

XMS512M 및 XMX1024로 XMS 및 XMX 매개 변수를 사용하여 JVM 초기 힙 크기 및 최대 힙 크기를 증가 시켰습니다. 여전히 파일에 150k 이상의 행을 쓸 수 없습니다.

메모리에 전체 파일을 작성하는 대신 Excel 파일로 스트리밍하는 방법을 찾고 있습니다. 대체 API 또는 솔루션은 모두 높이 평가되지만 Java 사용으로 제한됩니다. 감사! :)

도움이 되었습니까?

해결책

기존의 모든 Java API는 전체 문서를 RAM으로 한 번에 구축하려고합니다. 대신 새로운 XSLX 파일 형식을 준수하는 XML 파일을 작성하십시오. 시작하려면 Excel에서 원하는 양식으로 작은 파일을 작성하고 저장하는 것이 좋습니다. 그런 다음 그것을 열고 구조를 검사하고 원하는 부품을 교체하십시오.

Wikipedia는 a 전체 형식에 대한 좋은 기사.

다른 팁

사용하려고 노력하십시오 SXSSF 통합 문서, 거대한 XLS 문서, 빌드 문서 및 NIO를 사용하여 RAM을 전혀 먹지 않는 것은 좋은 일입니다.

힙 공간 예외를 극복하기 위해 파일을 여러 Excel 파일로 나누어야했습니다. 나는 22 개의 열이있는 약 5K 행이 그것에 관한 것이라고 생각했기 때문에 5k 행마다 파일을 끝내고 새 파일을 시작하고 그에 따라 파일을 숫자로 만들도록 논리를 만들었습니다.

20k + 행을 작성할 경우 데이터를 나타내는 4 개 이상의 다른 파일이 있습니다.

살펴보십시오 HSSF 시리얼 라이저 누에 고치 프로젝트에서.

HSSF Serializer는 색소폰 이벤트를 잡고 Microsoft Excel에서 사용하는 XLS 형식의 스프레드 시트를 만듭니다.

Jexcelapi도 있지만 더 많은 메모리를 사용합니다. .CSV 파일을 만들어 Excel에서 열어야한다고 생각합니다. 그것은 당신이 많은 데이터를 전달할 수 있지만, 당신은 "엑셀 마법"을 할 수 없을 것입니다.

CSV 형식 사용을 고려하십시오. 이렇게하면 더 이상 메모리로 제한되지 않습니다. 웰, 아마도 CSV의 데이터를 미리 구성하는 동안에 만 가능하지만 예를 들어 DB의 행의 쿼리 서브 세트를 예를 들어 사용하여 효율적으로 수행 할 수 있습니다. LIMIT/OFFSET 그리고 라인을 작성하기 전에 전체 DB 테이블 내용을 Java의 메모리로 운반하는 대신 즉시 파일에 작성하십시오. 하나의 "시트"에서 양상의 엑셀 제한은 약 백만으로 증가합니다.

즉, 데이터가 실제로 DB에서 나오면 Java가 올바른 도구라면 재고가 높아질 것입니다. 가장 괜찮은 DB는이 작업을 수행 할 수있는 내보내기 -CSV 기능이있어 훨씬 더 효율적으로 수행 할 수 있습니다. 예를 들어 MySQL의 경우 LOAD DATA INFILE 이것에 대한 명령.

이 목적을 위해 Java 라이브러리를 개발했으며 현재 오픈 소스 프로젝트로 제공됩니다. https://github.com/jbaliuka/x4j-analytic . 우리는 그것을 운영보고에 사용합니다. 우리는 거대한 Excel 파일을 생성합니다. ~ 200,000은 문제없이 작동하고 Excel은 그러한 파일을 열도록 관리합니다. 당사의 코드는 POI를 사용하여 템플릿을로드하지만 생성 된 컨텐츠는 메모리에 XML 또는 객체 모델 레이어없이 파일로 직접 스트리밍됩니다.

이 메모리 문제는 셀에 데이터를 삽입 할 때 또는 데이터 계산/생성을 수행 할 때 발생합니까?

사전 정의 된 정적 템플릿 형식으로 구성된 엑셀에 파일을로드하려면 템플릿을 저장하고 여러 시간을 재사용하는 것이 좋습니다. 일반적으로 템플릿 사례는 일일 판매 보고서를 생성 할 때 발생합니다.

그렇지 않으면, 처음부터 새 행, 테두리, 열 등을 만들어야 할 때마다.

지금까지 Apache Poi는 내가 찾은 유일한 선택입니다.

"명확하게, ~ 20k 행 (각 행에 약 10-20 개의 열이 있음)을 작성하면"java.lang.outofmemoryerRor : java 힙 스페이스 "가 있습니다.

"Enterprise IT"

당신이 할 수있는 일은 배치 데이터 삽입을 수행하는 것입니다. 1 페이지를 생성 한 후마다 Queuetask 테이블을 만들고 몇 초 동안 휴식을 취한 다음 두 번째 부분을 계속하십시오. 대기열 작업 중에 동적 데이터 변경에 대해 걱정이되면 먼저 기본 키를 Excel로 가져올 수 있습니다 (사용자보기에서 열을 숨기고 잠글면). 첫 번째 실행은 기본 키를 삽입 한 다음 두 번째 대기열 실행은 메모장에서 읽히고 작업 부분을 부분별로 수행합니다.

우리는 매우 비슷한 양의 데이터를 수행했으며 POI가 리소스가 너무 무겁기 때문에 Jexcelapi로 전환해야했습니다. Jexcelapi를 사용해보십시오. 큰 엑셀 파일을 조작해야 할 때 후회하지 않을 것입니다!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top