【问题标题】:Java.lang.OutOfMemoryError: null while writing on BufferedOutputStreamJava.lang.OutOfMemoryError:在 BufferedOutputStream 上写入时为空
【发布时间】:2022-01-14 03:01:57
【问题描述】:

我正在尝试从雪花结果集中读取数据,并根据我的要求通过附加所有列来构造一行。我有 1300 列要从结果集中读取。我写了下面的方法。

int available  = -1;
while (rs.next()) {
    for ( int i=1; i <= 1300; i++) {
        String value = rs.getString(i);
        if(value == null)
            value = "";
        row.append(value).append("\t");
    }
    byte[] line = (row.toString().trim()+"\n").getBytes(StandardCharsets.UTF_8);
    available = line.length;
    bufferedOutputStream.write(line, 0, available);
    row.setLength(0);
}
bufferedOutputStream.flush();
bufferedOutputStream.close();

这在 100K 记录之前有效,但当我尝试写入 100 万条记录时失败,

Java.lang.OutOfMemoryError: null
at java.base/java.io.ByteArrayOutputStream.hugeCapacity(ByteArrayOutputStream.java:125)
at java.base/java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:119)
at java.base/java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:95)
at java.base/java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:156)
at java.base/java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
at java.base/java.io.BufferedOutputStream.write(BufferedOutputStream.java:127)

如果我在上面说错了,请纠正我。基本上我需要写 1000 万条记录而不会出现内存问题。在此需要一些帮助,在此先感谢。

编辑: 我将其写入 ByteArrayOutputStream 以从 ByteArrayInputStream 作为 InputStream 读取。将从该输入流中读取数据以进行验证过程。

【问题讨论】:

  • 你似乎在写信给ByteArrayOutputStream
  • 您可以分配更多堆(假设您确实需要将所有数据都放在byte[] 中?)
  • 您的BufferedOutputStream 附加到什么位置?要处理 1000 万条记录,您需要通过流式传输到磁盘的内容来支持它。
  • @AndyBrown 我已在您提出问题后将其添加为编辑的一部分。谢谢!。我正在尝试将其写入 ByteArrayOutputStream 以便我可以从 Inputstream 中读取。我的验证工作只接受作为 Inputstream 的数据。
  • 创建一个临时文件。使用包裹在BufferedOutputStream 中的FileOutputStream 打开它。做你的处理。关闭文件。使用包裹在BufferedInputStream 中的FileInputStream 重新打开它,并将BufferedInputStream 提供给您的下游API。完成后删除文件。

标签: java sql snowflake-cloud-data-platform


【解决方案1】:

删除row

try {
    while (rs.next()) {
        for (int i = 1; i <= 1300; i++) {
            String value = rs.getString(i);
            if (value != null && !value.isEmpty()) {
                byte[] b = value.getBytes(StandardCharsets.UTF_8);
                bufferedOutputStream.write(b);
            }
            bufferedOutputStream.write('\t');
        }
        bufferedOutputStream.write('\n');
    }
} finally {
    bufferedOutputStream.close();
}

可能是您的 CBLOB 字段包含大量文本。然后rs.getString 可以被读者替换。

【讨论】:

  • 不错,但我仍然得到相同的 java.lang.OutOfMemoryError: null 错误。
  • ByteArrayOutputStream 用在哪里?希望不要包裹在上面的 BufferedOutputStream 中?注意:new ByteArrayOutputStream(400_000_000) 或类似的可能会有所帮助(减少调整大小)。使用压缩,GZipOutputStream 也是。
  • 是的,它包裹在 BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream);
猜你喜欢
  • 1970-01-01
  • 2013-12-11
  • 2014-12-02
  • 2011-09-21
  • 2012-03-14
  • 2014-03-23
  • 2012-06-03
  • 2014-10-05
相关资源
最近更新 更多