web-dev-qa-db-fra.com

Java - Réinitialisation de InputStream

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?

12
iMineLink

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.

7
kdgregory

Vous ne pouvez pas le faire de manière fiable; certains InputStreams (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.

2
chrylis

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();
1
Ravi Thapliyal

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

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.

0
androidguy