5 votes

Comment lire un gros fichier depuis Amazon S3 ?

J'ai un programme qui lit un fichier texte depuis Amazon s3, mais le fichier fait environ 400M. J'ai augmenté la taille de mon Heap mais je reçois toujours l'erreur Java Heap Size. Donc, je ne suis pas sûr que mon code soit correct ou non. J'utilise Amazon SDK pour Java et Guava pour traiter le flux de fichiers.

Veuillez m'aider

        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;

J'utilise cette option pour ma JVM. -Xms512m -Xmx2g . J'utilise ant pour exécuter le programme principal et j'ai donc inclus l'option jvm dans ANT_OPTS également. Mais cela ne fonctionne toujours pas.

8voto

Louis Wasserman Points 67557

Le point de InputSupplier -- bien que vous devriez utiliser ByteSource y CharSource ces jours-ci - est que vous ne devriez jamais avoir accès à la InputStream de l'extérieur, donc vous n'avez pas à vous rappeler de le fermer ou non.

Si vous utilisez une ancienne version de Guava avant ByteSource y CharSource ont été introduits, alors cela devrait être

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

Si vous utilisez Guava 14, cela peut être fait de manière plus fluide en tant que

    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();

Cela dit, votre fichier peut peser 400 Mo, mais Java String sont stockés en UTF-16, ce qui peut facilement doubler sa consommation de mémoire. Soit vous avez besoin de beaucoup plus de mémoire, soit vous devez trouver un moyen d'éviter de garder tout le fichier en mémoire en même temps.

7voto

pravinbhogil Points 83

Plutôt que de prendre tout le fichier en mémoire, vous pouvez lire le fichier par parties afin que tout le fichier ne soit pas en mémoire. Évitez de prendre tout le fichier en mémoire afin de ne pas avoir de problème de mémoire en raison d'une mémoire limitée.

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

//Allez dans la boucle maintenant et créez le fichier localement en lisant le contenu de s3 et ajoutez le fichier dans la boucle pour qu'il n'y ait pas tout le contenu en mémoire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X