Lire flux deux fois
Comment avez-vous lu la même inputstream deux fois? Est-il possible de copier quelque sorte?
J'ai besoin d'obtenir une image à partir du web, enregistrer localement et de revenir à l'enregistrement de l'image. Je viens de tought il serait plus rapide d'utiliser le même cours d'eau au lieu de commencer un nouveau flux de données pour le contenu téléchargé, puis le lire à nouveau.
- Peut-être utiliser la marque et de réinitialisation
Vous devez vous connecter pour publier un commentaire.
Vous pouvez utiliser
org.apache.commons.io.IOUtils.copie
pour copier le contenu de l'InputStream à un tableau d'octets, et ensuite à plusieurs reprises de lire à partir du tableau d'octets à l'aide d'un ByteArrayInputStream. E. g.:InputStream
est lu (il est lu à l'interne comme vous le mentionnez), alors vous pouvez être hors de la chance. Avez-vous accès à laInputStream
avant le l '"intérieur" de la lire? Je pense que le point @Ankit fait était différent et c'était juste concernant l'API.Selon l'endroit où l'InputStream est à venir à partir de, vous pourriez ne pas être en mesure de le réinitialiser. Vous pouvez vérifier si
mark()
etreset()
sont pris en charge à l'aide demarkSupported()
.Si elle l'est, vous pouvez appeler
reset()
sur l'InputStream pour revenir au début. Si non, vous devez lire l'InputStream à partir de la source de nouveau.BufferedInputStream
prend en charge la "marque"si votre
InputStream
en charge l'utilisation de la marque, alors vous pouvezmark()
votre inputStream et puisreset()
il . si votreInputStrem
ne supporte pas la marque, alors vous pouvez utiliser la classejava.io.BufferedInputStream
,de sorte que vous pouvez intégrer vos flux à l'intérieur d'unBufferedInputStream
comme ceBufferedInputStream.fill()
, il y a le "grandir tampon" de la section, où la nouvelle taille de la mémoire tampon est comparée qu'àmarklimit
etMAX_BUFFER_SIZE
.Vous pouvez envelopper les flux d'entrée avec PushbackInputStream. PushbackInputStream permet de non lus ("écrire de nouveau") octets qui ont déjà lu, de sorte que vous pouvez le faire comme ceci:
Veuillez noter que PushbackInputStream magasins interne de la mémoire tampon d'octets de sorte qu'il crée vraiment une mémoire tampon qui est titulaire d'octets "écrit".
Sachant que cette approche nous permet d'aller plus loin et de le combiner avec FilterInputStream. FilterInputStream magasins d'entrée original stream en tant que délégué. Cela permet de créer de nouveaux définition de la classe qui permet de "non lus" origine des données automatiquement. La définition de cette classe est la suivante:
Cette classe a deux méthodes. Un pour la lecture en mémoire tampon existante (définition est analogue à l'appel de
public int read(byte b[], int off, int len)
de la classe InputStream). Deuxième qui retourne un nouveau tampon (cela peut être plus efficace si la taille de la mémoire tampon de lecture est inconnu).Maintenant, nous allons voir notre classe en action:
Si vous utilisez une mise en œuvre de
InputStream
, vous pouvez vérifier le résultat deInputStream#markSupported()
que vous dire si oui ou non vous pouvez utiliser la méthodemarque()
/reset()
.Si vous pouvez marquer le ruisseau quand vous lisez, puis d'appeler
reset()
à revenir en arrière pour commencer.Si vous ne pouvez pas vous aurez à ouvrir un flux de données.
Une autre solution serait de convertir InputStream de tableau d'octets, puis itérer sur le tableau autant de fois que vous en avez besoin. Vous pouvez trouver plusieurs solutions dans ce post Convertir InputStream de tableau d'octets en Java à l'aide de la 3ème partie du syndicat ou non. Attention, si la lecture de contenu est trop grand, vous risquez de rencontrer certains des troubles de la mémoire.
Enfin, si votre besoin est de lire l'image, puis utilisez :
À l'aide de
ImageIO#lire(java.net.URL)
vous permet également d'utiliser le cache.ImageIO#read(java.net.URL)
: certains serveurs web et les Cdn peuvent rejeter nu appels (c'est à dire sans un Utilisateur Agent qui fait que le serveur croyons que l'appel provient d'un navigateur web) faite parImageIO#read
. Dans ce cas, à l'aide deURLConnection.openConnection()
réglage de l'agent utilisateur pour la connexion + à l'aide de `ImageIO.lire(InputStream), le plus de temps, faire le tour.InputStream
n'est pas une interfaceComment sur:
Convertir inputstream en octets et puis la passer à savefile fonction de l'endroit où vous assemblez le même dans inputstream.
Également en fonction d'origine de l'utilisation d'octets à utiliser pour d'autres tâches
Au cas où quelqu'un est en cours d'exécution, au Printemps de Démarrage de l'app, et vous voulez lire le corps de la réponse d'un
RestTemplate
(c'est pourquoi je veux lire un flux à deux reprises), il est propre(re) manière de faire.Tout d'abord, vous devez utiliser le Printemps
StreamUtils
de copier le flux d'une Chaîne de caractères:Mais ce n'est pas tout. Vous devez également utiliser une demande d'usine qui peuvent tampon du flux pour vous, comme:
Ou, si vous êtes à l'aide de l'usine, de haricots, puis (c'est Kotlin, mais quand même):
Source: https://objectpartners.com/2018/03/01/log-your-resttemplate-request-and-response-without-destroying-the-body/
Pour diviser une
InputStream
en deux, tout en évitant de charger toutes les données en mémoire, puis de les traiter de manière indépendante:OutputStream
, précisément:PipedOutputStream
PipedInputStream
sont retournésInputStream
.OutputStream
. Donc, tout lire depuis le sourcingInputStream
, serait écrite dans les deuxOutputStream
. Il n'y a pas besoin de mettre en œuvre, parce que c'est déjà fait dansTeeInputStream
(commons.io).Dans un thread séparé de lire l'ensemble de l'approvisionnement inputStream, et, implicitement, les données d'entrée est transférée à la cible inputStreams.
Être conscient de fermer la inputStreams après avoir été consommé, et fermer le thread qui s'exécute:
TeeInputStream.readAllBytes()
Dans le cas, vous devez de le diviser en plusieurs
InputStream
, au lieu de deux. Remplacer le précédent, le fragment de code de la classeTeeOutputStream
pour votre propre mise en œuvre, qui résumerait unList<OutputStream>
et remplacer leOutputStream
interface: