我正在使用字符串缓冲区和字节数组创建两个 CSV 文件。
我使用 ZipOutputStream
生成 zip 文件。每个 csv 文件将包含 14 列的 20K 条记录。实际上,记录是从数据库中获取的,并存储在 ArrayList
中。我必须迭代列表并构建 StringBuffer
并将 StringBuffer
转换为字节数组以将其写入 zip 条目。
我想知道 JVM 完成从将记录存储在ArrayList
中开始的整个过程所需的内存。
我在下面提供了代码片段。
StringBuffer responseBuffer = new StringBuffer();
String response = new String();
response = "Hello, sdksad, sfksdfjk, World, Date, ask, askdl, sdkldfkl, skldkl, sdfklklgf, sdlksldklk, dfkjsk, dsfjksj, dsjfkj, sdfjkdsfj\n";
for(int i=0;i<20000;i++){
responseBuffer.append(response);
}
response = responseBuffer.toString();
byte[] responseArray = response.getBytes();
res.setContentType("application/zip");
ZipOutputStream zout = new ZipOutputStream(res.getOutputStream());
ZipEntry parentEntry = new ZipEntry("parent.csv");
zout.putNextEntry(parentEntry);
zout.write(responseArray);
zout.closeEntry();
ZipEntry childEntry = new ZipEntry("child.csv");
zout.putNextEntry(childEntry);
zout.write(responseArray);
zout.closeEntry();
zout.close();
请帮我解决这个问题。提前致谢。
最佳答案
我猜您已经尝试计算将分配给 StringBuffer 和字节数组的字节数。但问题是,除非您对 CSV 记录的大小有上限,否则您无法真正知道您的应用程序将使用多少内存。我是 如果您希望您的软件稳定、健壮和可扩展,恐怕您问错了问题:您应该努力使用固定数量的内存执行您需要执行的任务,在您的情况下似乎很容易实现。
关键是,在您的情况下,处理完全是 FIFO - 您从数据库中读取记录,然后将它们(以相同的顺序)写入 FIFO 流(OutputStream
在这种情况下).即使是 zip 压缩也是基于流的,并且在内部使用固定数量的内存,所以你在那里是完全安全的。
不是将整个输入缓冲在一个巨大的字符串中,然后将其转换为一个巨大的字节数组,然后将其写入输出流 - 您应该从数据库中单独读取每个响应元素(或固定大小的 block ,比如 100一次记录),并将其写入输出流。有点像
res.setContentType("application/zip");
ZipOutputStream zout = new ZipOutputStream(res.getOutputStream());
ZipEntry parentEntry = new ZipEntry("parent.csv");
zout.putNextEntry(parentEntry);
while (... fetch entries ...)
zout.write(...data...)
zout.closeEntry();
这种方法的优点是,因为它适用于小块,所以您可以轻松估计它们的大小,并为您的 JVM 分配足够的内存,这样它就不会崩溃。而且您知道,如果您的 CSV 文件将来超过 20K 行,它仍然可以工作。
关于java - JVM 创建 CSV 文件并即时压缩所需的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13902316/