3
votes

Comment obtenir Inputstream à partir de Java 8 Streams?

J'ai des données diffusées à partir de différents fichiers. Il est au format suivant:

Stream<String> linesModifiedAndAppendedFromVariousFiles=getLines();

Cependant, je dois alimenter ceci dans une méthode de bibliothèque qui accepte InputStream ou Reader comme paramètre.

Comment puis-je alimenter ceci Java 8 flux dans un InputStream ou un type de Reader?

PS: il ne s'agit pas d'encapsuler java.util.streams.Stream autour d'un InputStream. Ce que je recherche, c'est l'inverse.


4 commentaires

Un Stream n'a rien à voir avec InputStream . Ces deux packages sont entièrement différents.


Copie possible de Comment puis-je utiliser Java 8 Streams avec un InputStream?


@MuratKaragoz je sais! Il n'y a rien dans les questions qui le prétend. Il devrait y avoir (j'espère) un moyen de créer un Inputsream qui accepte les flux Java 8 comme source.


@ MuratKaragöz Non, celui-ci consiste à envelopper java.util.stream.Stream autour d'un InputStream. Ce dont j'ai besoin, c'est l'inverse.


3 Réponses :


1
votes

Une séquence java.util.Stream est conceptuellement une séquence potentiellement infinie et non inverseuse (comme dans, une fois que vous dépassez une entrée, vous ne pouvez pas y revenir), ce qui peut potentiellement vous permettre pour le traiter en parallèle. Surtout, les «trucs» de la séquence peuvent être du tout TOUT . Par exemple, vous pouvez avoir un flux d'objets Color.

Un java.io.InputStream est conceptuellement une séquence d'octets potentiellement infinie, non inverseuse et non parallélisable.

Ces 2 choses ne sont tout simplement pas les mêmes.

Cependant, si vous avez un Stream d'octets spécifiquement, vous pouvez le transformer en flux d'entrée. Vous choisissez simplement de ne pas utiliser l'option de parallellisation inhérente à Stream, puis ces 2 choses commencent à se résumer à la même chose. Cependant, si vous avez un flux de tout ce qui n'est pas un octet, vous devrez trouver le 'mapping'.

Disons que vous avez un flux d'objets chaîne. Disons que c'est un flux des 4 premiers nombres en anglais (donc: Arrays.asList ("one", "two", "three", "four"). Stream () ).

Comment voulez-vous mapper ce flux de chaînes en un flux d'octets? Une stratégie pourrait être de rendre les chaînes en octets en utilisant le codage UTF-8 et d'utiliser le caractère 0 comme séparateur. En d'autres termes, que vous voulez le même résultat que cet hypothétique: new ByteArrayInputStream (new String ("one \ 0two \ 0three \ 0four"). GetBytes (StandardCharsets.UTF_8)) .

On peut imaginer une fonction qui prend un Stream et le transforme en InputStream. Cependant, un Stream serait un concept très inefficace. On peut aussi imaginer une fonction qui prend un Stream avec une fonction de mappage mappant T à byte [] , et une constante de séparateur (ou fonction qui génère une valeur) qui produit les séparateurs. Pour l'exemple ci-dessus, quelque chose comme:

toInputStream(oneTwoThreeFour, str -> str.getBytes(StandardCharsets.UTF_8), "\0");

pour autant que je sache, cela n'existe pas dans les bibliothèques principales ni dans des endroits comme la goyave. Mais l'écrire devrait être assez trivial. Peut-être une demi-page de code.


0 commentaires

2
votes

Vous pouvez le faire avec PipedReader et PipedWriter .

PipedReader reader = new PipedReader();

Runnable feeder = new Runnable() {
    @Override
    public void run() {
        try (PipedWriter writer = new PipedWriter(reader)) {
            linesModifiedAndAppendedFromVariousFiles.forEachOrdered(line -> {
                try {
                    writer.write(line);
                    writer.write('\n');
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
};
new Thread(feeder).start();

someLibraryMethod.consumeReader(reader);


2 commentaires

Merci pour la réponse. Le fait est que, ici, forEachOrdered est une opération de terminal, par conséquent, il termine le flux. Mais je veux que ce soit un flux infini constamment peuplé. Comment puis-je réaliser la même chose ci-dessus avec ces informations?


forEachOrdered continuera jusqu'à ce que le Stream soit fermé. forEachOrdered ne ferme ni ne termine lui-même un Stream.



0
votes

Flux de lecture d'octets:

private Thread infinitInputStreamSupplierThread(final PipedInputStream inputStream) {
        return new Thread(() -> {
            try (PipedOutputStream outputStream = new PipedOutputStream(inputStream)) {
                Stream<byte[]> infiniteStream = Stream.generate(randomByteSupplier());
                infiniteStream.forEachOrdered(bytes -> {
                    try {
                        outputStream.write(bytes);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    private Supplier<byte[]> randomByteSupplier() {
        return () -> {
            byte[] bytes = new byte[100];
            new Random().nextBytes(bytes);

            return bytes;
        };
    }

Voici les méthodes pour générer un flux d'entrée

    PipedInputStream inputStream = new PipedInputStream();
    Thread infinitInputStreamSupplier = infinitInputStreamSupplierThread(inputStream);
    infinitInputStreamSupplier.start();
    //consume input stream here...
    infinitInputStreamSupplier.interrupt();


0 commentaires