首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当尝试对中等大小的XLSX工作簿(~=80MB)进行密码保护时,Apache POI抛出OOM错误

当尝试对中等大小的XLSX工作簿(~=80MB)进行密码保护时,Apache POI抛出OOM错误
EN

Stack Overflow用户
提问于 2020-04-28 00:13:02
回答 2查看 219关注 0票数 0

使用java 8和apache POI和POI-OOXML 3.14

下面是我的方法:

代码语言:javascript
复制
    private static void encryptXlsx(String inputPath, String outputPath, String password) throws IOException, InvalidFormatException, GeneralSecurityException {
    //create a new workbook
    Workbook wb = WorkbookFactory.create(new File(inputPath));


    //Add password protection and encrypt the file
    POIFSFileSystem fs = new POIFSFileSystem();
    EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
    Encryptor enc = info.getEncryptor();
    enc.confirmPassword(password); // s3cr3t is your password to open sheet.

    OPCPackage opc = OPCPackage.open(new File(inputPath), PackageAccess.READ_WRITE);
    OutputStream os = enc.getDataStream(fs);
    opc.save(os);
    opc.close();

    FileOutputStream fos = new FileOutputStream(outputPath);
    fs.writeFilesystem(fos);
    fos.close();
}

错误堆栈为:

代码语言:javascript
复制
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3044)
at org.apache.xmlbeans.impl.store.Cur$CurLoadContext.attr(Cur.java:3065)
at org.apache.xmlbeans.impl.store.Locale$SaxHandler.startElement(Locale.java:3263)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.reportStartTag(Piccolo.java:1082)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseAttributesNS(PiccoloLexer.java:1802)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseOpenTagNS(PiccoloLexer.java:1521)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseTagNS(PiccoloLexer.java:1362)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXMLNS(PiccoloLexer.java:1293)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.parseXML(PiccoloLexer.java:1261)
at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.yylex(PiccoloLexer.java:4812)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yylex(Piccolo.java:1290)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.yyparse(Piccolo.java:1400)
at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:714)
at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3479)
at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1277)
at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1264)
at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
at org.apache.poi.POIXMLTypeLoader.parse(POIXMLTypeLoader.java:92)
at org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument$Factory.parse(Unknown Source)
at org.apache.poi.xssf.usermodel.XSSFSheet.read(XSSFSheet.java:173)
at org.apache.poi.xssf.usermodel.XSSFSheet.onDocumentRead(XSSFSheet.java:165)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.parseSheet(XSSFWorkbook.java:417)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.onDocumentRead(XSSFWorkbook.java:382)
at org.apache.poi.POIXMLDocument.load(POIXMLDocument.java:178)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:249)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:293)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:252)
at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:231)
at XlsxEncryptExample.encryptXlsx(XlsxEncryptExample.java:36)
at XlsxEncryptExample.main(XlsxEncryptExample.java:28)

进程已完成,退出代码为%1

如果有人能告诉我一种在不使用这么多内存的情况下读取这个文件的方法,一个比POI或任何其他可能的解决方案更好地进行密码保护的库,我将不胜感激。

EN

回答 2

Stack Overflow用户

发布于 2020-04-28 01:55:06

据我所知,documentation POI通常将整个电子表格读取到内存中。上面确实写着

注意,usermodel系统比低级eventusermodel占用更多的内存,但主要的优点是使用起来要简单得多。还请注意,由于新的支持XSSF的Excel2007OOXML (.xlsx)文件是基于可扩展标记语言的,因此处理它们所占用的内存比旧的支持HSSF (.xls)的二进制文件要高。

它继续提供低内存占用的替代方案。

票数 1
EN

Stack Overflow用户

发布于 2020-04-29 01:08:00

代码语言:javascript
复制
private static void encryptXlsx(String inputPath, String outputPath, String password) throws IOException, InvalidFormatException, GeneralSecurityException {
//create a new workbook
//Workbook wb = WorkbookFactory.create(new File(inputPath));


//Add password protection and encrypt the file
POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword(password); // s3cr3t is your password to open sheet.

OPCPackage opc = OPCPackage.open(new File(inputPath), PackageAccess.READ_WRITE);
OutputStream os = enc.getDataStream(fs);
opc.save(os);
opc.close();

FileOutputStream fos = new FileOutputStream(outputPath);
fs.writeFilesystem(fos);
fos.close();

}

取消对工作簿工厂的调用似乎对我很有效。事实证明,你不需要加载整个文件来进行密码保护。然而,对于任何想要操作文件内容的人来说,仍然不能解决这个问题,所以我没有解决这个问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61463301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档