英文:
Jasper report exporting to text results in java.lang.OutOfMemoryError: Java heap space
问题
目前我正在使用jasper v `3.7.4`
从相同的`数据集`导出到任何其他格式(`csv`、`xls`、`pdf`)时,我没有任何问题。
导出到`text`会抛出:
> java.lang.OutOfMemoryError: Java heap space at
> java.util.Arrays.copyOf(Arrays.java:3236) at
> java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
以下是我的代码:
```java
byte[] bytes = null;
JRTextExporter exporter = new JRTextExporter();
ByteArrayOutputStream txtReport = new ByteArrayOutputStream();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, txtReport);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, "mytxt.txt");
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH, 2.0F);
exporter.setParameter(JRTextExporterParameter.PAGE_WIDTH, 100.0F);
exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT, 4.0F);
exporter.setParameter(JRTextExporterParameter.PAGE_HEIGHT, 50.0F);
exporter.exportReport();
bytes = txtReport.toByteArray();
FileOutputStream fos = new FileOutputStream("c:\\myfile.txt");
System.out.println(bytes.length/1024 + " Kbytes");
fos.write(bytes, 0, bytes.length);
fos.flush();
fos.close();
我还将jasperPrint
参数设置为了一个virtualizer
JRFileVirtualizer virtualizer = new JRFileVirtualizer(150);
virtualizer.setReadOnly(false);
params.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
但是这并没有起作用,并且还会显示以下警告:
> WARNING: Parameter "REPORT_VIRTUALIZER" already registered, skipping
> this one.
鉴于csv
也是一个“text
”文件,并且可以正常生成,导出到text
失败有点奇怪。
也许我为导出器提供的参数有问题?
谢谢。
<details>
<summary>英文:</summary>
Currently I am using jasper v `3.7.4`
While exporting to any other format (`csv`,`xls`,`pdf`) from the same `dataset` - I have has no issues.
Exporting to `text` throws:
> java.lang.OutOfMemoryError: Java heap space at
> java.util.Arrays.copyOf(Arrays.java:3236) at
> java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
Here is my code:
byte[] bytes = null;
JRTextExporter exporter = new JRTextExporter();
ByteArrayOutputStream txtReport = new ByteArrayOutputStream();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, txtReport);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, "mytxt.txt");
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH, 2.0F);
exporter.setParameter(JRTextExporterParameter.PAGE_WIDTH, 100.0F);
exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT, 4.0F);
exporter.setParameter(JRTextExporterParameter.PAGE_HEIGHT, 50.0F);
exporter.exportReport();
bytes = txtReport.toByteArray();
FileOutputStream fos = new FileOutputStream("c:\\myfile.txt")
System.out.println(bytes.length/1024+" Kbytes");
fos.write(bytes, 0, bytes.length);
fos.flush();
fos.close();
I am also using a `virtualizer` as `jasperPrint` parameter
JRFileVirtualizer virtualizer = new JRFileVirtualizer(150);
virtualizer.setReadOnly(false);
params.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
But it does not help, and also the following warning is shown:
> WARNING: Parameter "REPORT_VIRTUALIZER" already registered, skipping
> this one.
Given that `csv` is also a "`text`" file and is generated without any problem, it is kind of strange that
exporting to `text` fails.
May be something is wrong with the parameters I provide for the exporter?
Thanks.
</details>
# 答案1
**得分**: 2
虽然 `text` 和 `csv` 都可能是基于*文本*的格式,但它们并不是*相同*的格式,因此不会占用相同的空间。
将*任何内容*(通常是报告)生成到内存中是危险的,因为虽然在测试中可能有效,但在生产中,生成一个大型报告可能导致 OOME(内存耗尽错误),从而造成严重混乱。
在生成内容时,请使用真实的流。例如,`FileOutputStream`、网络流,或者任何不会将内容存储在内存中的适当流。如果你在进行“真实工作”时使用 `ByteArrayOutputStream`,很可能出现了错误操作。
<details>
<summary>英文:</summary>
While `text` and `csv` may both be *text based* formats, they're not the *same* format and therefore do not take the same amount of space.
Generating *anything* (usually reports) to memory is hazardous since while it may work in testing, a large report in production causing an OOME will wreak havoc.
Use a real stream when generating things. A `FileOutputStream`, network stream, any proper stream that doesn't store things in memory. If you're using a `ByteArrayOutputStream` for "real work", you're most likely doing something wrong.
</details>
# 答案2
**得分**: 0
立即将报告输出到文件,而不是先收集报告。
```java
try (FileOutputStream fos = new FileOutputStream("c:\\myfile.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
JRTextExporter exporter = new JRTextExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, bos);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, "mytxt.txt");
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH, 2.0F);
exporter.setParameter(JRTextExporterParameter.PAGE_WIDTH, 100.0F);
exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT, 4.0F);
exporter.setParameter(JRTextExporterParameter.PAGE_HEIGHT, 50.0F);
exporter.exportReport();
}
英文:
Immediately output the report to the file, instead of first collecting it.
try (FileOutputStream fos = new FileOutputStream("c:\\myfile.txt");
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
JRTextExporter exporter = new JRTextExporter();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, bos);
exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, "mytxt.txt");
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
exporter.setParameter(JRTextExporterParameter.CHARACTER_WIDTH, 2.0F);
exporter.setParameter(JRTextExporterParameter.PAGE_WIDTH, 100.0F);
exporter.setParameter(JRTextExporterParameter.CHARACTER_HEIGHT, 4.0F);
exporter.setParameter(JRTextExporterParameter.PAGE_HEIGHT, 50.0F);
exporter.exportReport();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论