我正在尝试更新嵌入在 ppt 幻灯片中的空 excel,并且正在使用小尺寸 excel 文件,但是使用包含更多数据的 excel 文件会引发错误:更新 xssfworkbook 超出了 gc 开销限制
我当前的代码是这样的:
PackagePart embeddedFile = null;
for (PackagePart packagePart : ppt.getAllEmbeddedParts()) {
if ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equalsIgnoreCase(packagePart.getContentType())) {
firstEmbeddedExcelPackagePart = packagePart;
}
}
if (embeddedFile != null) {
InputStream inputStream = getExcelInputStream();
XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
OutputStream os = firstEmbeddedExcelPackagePart.getOutputStream();
workbook.write(os);
workbook.close();
os.close();
}
然后我尝试通过在上面的一行中执行此更新来解决该错误,但得到了这个新错误 java.lang.OutOfMemoryError: Java heap space
....
SXSSFWorkbook workbook = new SXSSFWorkbook(new XSSFWorkbook(inputStream), 100, true, true);
...
然后尝试通过更新此值-Xmx8192m来更新intellij中的jvm配置,但得到了相同的第一个错误。
有没有办法处理大尺寸的 Excel 文件,以便更新 ppt 幻灯片(空文件)中现有的嵌入 Excel 文件,或者选择创建要嵌入的文件而不是更新模板 Excel 文件?
谢谢您的回答。
请参阅 错误 java.lang.OutOfMemoryError:超出 GC 开销限制,原因为
java.lang.OutOfMemoryError: GC overhead limit exceeded
。
此消息意味着由于某种原因垃圾收集器正在运行 花费过多的时间......并且恢复很少的记忆 在每次运行中。
我见过这种情况发生的罕见情况是 一些代码创建了大量的临时对象和大量的 内存已经非常有限的弱引用对象 环境。
这里也是如此。
我想您的代码的完整示例类似于我在 Updateembedded worksheet in ppt Slide apache poi中的答案。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.apache.poi.xslf.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.openxml4j.opc.PackagePart;
public class PPTXReplaceEmbeddedExcel {
public static void main(String[] args) {
try ( XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream("./TableSample.pptx"));
FileOutputStream out = new FileOutputStream("./TableSampleNew.pptx"); ) {
PackagePart firstEmbeddedExcelPackagePart = null;
for (PackagePart packagePart : slideShow.getAllEmbeddedParts()) {
System.out.println(packagePart.getContentType());
if ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equals(packagePart.getContentType())) {
firstEmbeddedExcelPackagePart = packagePart;
}
}
if (firstEmbeddedExcelPackagePart != null) {
try ( FileInputStream fis = new FileInputStream("./Excel.xlsx");
XSSFWorkbook workbook = new XSSFWorkbook(fis);
OutputStream os = firstEmbeddedExcelPackagePart.getOutputStream(); ) {
// do something with workbook...
workbook.write(os);
}
}
slideShow.write(out);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
那里
XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream("./TableSample.pptx"))
从 Office Open XML 文件格式的 PowerPoint 文件创建 XMLSlideShow。这意味着解压缩 Office Open XML 文件格式 ZIP、读取 XML 并创建大量 Java 对象(Apache POI XSLF
对象,以及从 PowerPoint 文件的 MIcrosofts XML 模式创建的大量 XMLBeans
对象)。之后,XSSFWorkbook workbook = new XSSFWorkbook(fis)
对 Office Open XML 文件格式的 Excel 文件中的 XSSFWorkbook
执行相同的操作。这意味着解压缩 Office Open XML 文件格式 ZIP、读取 XML 并创建大量 Java 对象(Apache POI XSSF
对象,以及从 Excel 文件的 MIcrosofts XML 架构创建的大量 XMLBeans
对象)。
毕竟,我们在内存中拥有大量用于
XSLF
、XSSF
的 Java 对象,以及通过 XMLBeans
从 Microsoft 用于 PowerPoint 和 Excel 的 XML 方案创建的两种低级 Java 对象。
这会消耗内存和CPU。
如果只是从 Excel 文件的全部内容更新
firstEmbeddedExcelPackagePart
而不操作工作簿,则不需要创建 XSSFWorkbook
。然后您只需将Excel文件内容复制到嵌入包部分的OutputStream
即可。这至少省去了创建 XSSFWorkbook
的麻烦。
...
if (firstEmbeddedExcelPackagePart != null) {
try ( FileInputStream fis = new FileInputStream("./Excel.xlsx");
//XSSFWorkbook workbook = new XSSFWorkbook(fis);
OutputStream os = firstEmbeddedExcelPackagePart.getOutputStream(); ) {
// do something with workbook...
//workbook.write(os);
fis.transferTo(os);
}
}
...