Je traite d'un code Java dans lequel il y a un InputStream que je lis une fois et que je dois ensuite le relire de la même manière.
Le problème est que je dois réinitialiser sa position au début pour pouvoir la lire deux fois.
J'ai trouvé une solution astucieuse au problème:
is.mark(Integer.MAX_VALUE);
//Read the InputStream is fully
// { ... }
try
{
is.reset();
}
catch (IOException e)
{
e.printStackTrace();
}
Cette solution entraîne-t-elle des comportements inattendus? Ou cela fonctionnera-t-il dans son mutisme?
Comme vous l'avez écrit, vous n'avez aucune garantie, car mark()
n'est pas obligé d'indiquer s'il a réussi. Pour obtenir une garantie, vous devez d'abord appeler markSupported () , et il doit renvoyer true
.
De plus, comme écrit, la limite de lecture spécifiée est très dangereuse. Si vous utilisez un flux qui stocke la mémoire tampon en mémoire tampon, il allouera potentiellement un tampon de 2 Go. D'un autre côté, si vous utilisez une FileInputStream
, tout va bien.
Une meilleure approche consiste à utiliser une variable BufferedInputStream
avec un tampon explicite.
Vous ne pouvez pas le faire de manière fiable; certains InputStream
s (tels que ceux connectés à des terminaux ou à des sockets) ne supportent pas mark
et reset
(voir markSupported
). Si vous devez vraiment traverser les données deux fois, vous devez les lire dans votre propre tampon.
Au lieu d'essayer de réinitialiser la variable InputStream
, chargez-la dans une mémoire tampon du type StringBuilder
ou s'il s'agit d'un flux de données binaires, une variable ByteArrayOutputStream
. Vous pouvez ensuite traiter le tampon dans la méthode autant de fois que vous le souhaitez.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int read = 0;
byte[] buff = new byte[1024];
while ((read = inStream.read(buff)) != -1) {
bos.write(buff, 0, read);
}
byte[] streamData = bos.toByteArray();
Cela dépend de l'implémentation InputStream. Vous pouvez également penser s'il sera préférable d'utiliser byte []. Le plus simple est d’utiliser Apache commons-io :
byte[] bytes = IOUtils.toByteArray(inputSream);
Pour moi, la solution la plus simple consistait à transmettre l'objet à partir duquel obtenir le flux d'entrée et de le récupérer. Dans mon cas, c'était d'un ContentResolver
.