2017-06-13 21 views
1

我想从S3读取和写入InMemory缓冲区,如:阅读S3对象和写入InMemory缓冲区

def inMemoryDownload(bucketName: String, key: String): String = { 
    val s3Object = s3client.getObject(new GetObjectRequest(bucketName, key)) 
    val s3Stream = s3Object.getObjectContent() 
    val outputStream = new ByteArrayOutputStream() 
    val buffer = new Array[Byte](10* 1024) 
    var bytesRead:Int =s3Stream.read(buffer) 
    while (bytesRead > -1) { 
    info("writing.......") 
    outputStream.write(buffer) 
    info("reading.......") 
    bytesRead = ss3Stream.read(buffer) 
    } 
    val data = new String(outputStream.toByteArray) 
    outputStream.close() 
    s3Object.getObjectContent.close() 
    data 
} 

但它给我的堆空间误差(文件上S3大小为4MB)

+0

您可能需要检查堆内存。另外,不建议在堆内存中使用4mb数据。 – notionquest

+0

我的JVM堆大小是1G。 – developer

回答

0

在写入流时,您应该使用刚刚读取的字节数。你写它的方式,每次写入整个缓冲区。我怀疑这是你记忆力问题的原因,但它可能是。想象一下,read每次都会向您返回一个字节,并且您将10K写入流中。那是40G,就在那里。

另一个问题是,我不是100%确定,但我怀疑,getObjectObject每次都会创建一个新的输入流。基本上,你只是在循环中一遍又一遍地读相同的字节。你应该把它变成一个变量。另外,如果我可以提出一个建议,试着用实际的scala重写你的代码,不仅仅是语法上的,而且是地道的。避免可变状态,并使用功能转换。如果你打算编写Scala代码,不妨花一些时间来进入正确的思维模式。你会变得最终欣赏它,我保证:)

这样的事情,也许?

val input = s3Object.getObjectContent 
Stream 
    .continually(input.read(buffer)) 
    .takeWhile(_ > 0) 
    .foreach { output.write(buffer, 0, _) } 
+0

谢谢。在变量中分配流。但它仍然无法正常工作。 – developer

+0

不确定你的意思是“仍然没有工作”。我上面写的代码确实有效。 – Dima

+0

获取堆空间错误 – developer