2013-04-18 192 views
3

我有一个程序会从亚马逊s3读取文本文件,但文件大约400M。我增加了堆大小,但仍然收到Java堆大小错误。所以,我不确定我的代码是否正确。我正在使用Amazon SDK for Java和Guava来处理文件流。如何从Amazon S3读取大文件?

请帮

 

     S3Object object = s3Client.getObject(new GetObjectRequest(bucketName, folder + filename)); 
     final InputStream objectData = object.getObjectContent(); 

     InputSupplier supplier = CharStreams.newReaderSupplier(new InputSupplier() { 
      @Override 
      public InputStream getInput() throws IOException { 
       return objectData; 
      } 
     }, Charsets.UTF_8); 

     String content = CharStreams.toString(supplier); 
     objectData.close(); 

     return content; 
 

我使用这个选项我的JVM。 -Xms512m -Xmx2g。我使用ant来运行主程序,所以我也包括jvm选项到ANT_OPTS。但它仍然无法正常工作。

回答

6

InputSupplier点 - 尽管你应该使用ByteSourceCharSource这些天 - 是你不应该访问InputStream从外面,所以你不必记得关闭与否。

如果您使用ByteSourceCharSource之前的旧版本番石榴的相继出台,那么这应该是

InputSupplier supplier = CharStreams.newReaderSupplier(new InputSupplier() { 
     @Override 
     public InputStream getInput() throws IOException { 
      S3Object object = s3Client.getObject(
      new GetObjectRequest(bucketName, folder + filename)); 
      return object.getObjectContent(); 
     } 
    }, Charsets.UTF_8); 
    String content = CharStreams.toString(supplier); 

如果您使用番石榴14,那么可以更流畅完成为

new ByteSource() { 
     @Override public InputStream openStream() throws IOException { 
     S3Object object = s3Client.getObject(
      new GetObjectRequest(bucketName, folder + filename)); 
     return object.getObjectContent(); 
     } 
    }.asCharSource(Charsets.UTF_8).read(); 

这就是说:你的文件可能是400MB,但是Java Strings存储为UTF-16,它可以轻松地将内存消耗加倍。你可能需要更多的内存,或者你需要找出一种方法来避免将整个文件一次保存在内存中。

0

而不是采取内存中的整个文件,你可以阅读文件的部分,所以你的整个文件将不会在内存中。避免服用整个文件在内存中,这样你不会得到内存问题,由于内存有限

GetObjectRequest rangeObjectRequest = new GetObjectRequest(bucketName, key); 
rangeObjectRequest.setRange(0, 1000); // retrieve 1st 1000 bytes. 
S3Object objectPortion = s3Client.getObject(rangeObjectRequest); 
InputStream objectData = objectPortion.getObjectContent(); 

环路现在//你去通过读取S3内容制作文件和本地环路附加文件,并且不会有全部内容在内存中