5

我有一个程序可以从 Amazon s3 读取文本文件,但文件大小约为 400M。我增加了堆大小,但仍然收到 Java 堆大小错误。所以,我不确定我的代码是否正确。我正在使用 Amazon SDK for java 和 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_OPTS 中。但它仍然无法正常工作。

4

2 回答 2

8

要点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);

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

于 2013-04-18T17:48:37.960 回答
7

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

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

//现在进入循环并通过从s3读取内容并在循环中追加文件来在本地创建文件,因此内存中不会有全部内容

于 2018-01-21T20:09:48.810 回答