Java 如何从AmazonS3读取大文件?

Java 如何从AmazonS3读取大文件?,java,amazon-web-services,amazon-s3,guava,Java,Amazon Web Services,Amazon S3,Guava,我有一个程序可以从AmazonS3中读取文本文件,但是这个文件大约是400米。我已经增加了堆大小,但仍然出现Java堆大小错误。所以,我不确定我的代码是否正确。我正在使用AmazonSDKforJava和Guava来处理文件流 请帮忙 S3Object object = s3Client.getObject(new GetObjectRequest(bucketName, folder + filename)); final InputStream object

我有一个程序可以从AmazonS3中读取文本文件,但是这个文件大约是400米。我已经增加了堆大小,但仍然出现Java堆大小错误。所以,我不确定我的代码是否正确。我正在使用AmazonSDKforJava和Guava来处理文件流

请帮忙


        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_选项中。但它仍然不起作用

InputSupplier的要点是,尽管您现在应该使用
ByteSource
CharSource
,但您不应该从外部访问
InputStream
,因此您不必记得是否关闭它

如果在引入
ByteSource
CharSource
之前使用的是旧版本的番石榴,那么这应该是

    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
String
s存储为UTF-16,这很容易使其内存消耗翻一番。您可能需要更多的内存,或者您需要找到一种方法来避免将整个文件一次保存在内存中。

您可以将文件逐部分读取,而不是将整个文件保存在内存中。避免将整个文件放在内存中,这样您就不会因为内存有限而出现内存问题

GetObjectRequest rangeObjectRequest = new GetObjectRequest(bucketName, key);
rangeObjectRequest.setRange(0, 1000); // retrieve 1st 1000 bytes.
S3Object objectPortion = s3Client.getObject(rangeObjectRequest);
InputStream objectData = objectPortion.getObjectContent();
//现在进入循环,通过读取s3中的内容在本地生成文件,并在循环中追加文件,这样内存中就不会有完整的内容