web-dev-qa-db-fra.com

Dois-je toujours envelopper un InputStream en tant que BufferedInputStream?

Est-il judicieux de toujours envelopper un InputStream en tant que BufferedInputStream, quand je sais si le InputStream donné est autre chose que tampon? Par exemple:

InputStream is = API.getFromSomewhere()
if(!(is instanceof BufferedInputStream))
  return new BufferedInputStream(is);
return is;
40
geejay

Est-il logique de toujours encapsuler un InputStream en tant que BufferedInputStream, quand je sais si le InputStream donné est autre chose que tampon?

Non.

Cela a du sens si vous êtes susceptible d'effectuer de nombreuses petites lectures (un octet ou quelques octets à la fois), ou si vous souhaitez utiliser certaines des fonctionnalités de niveau supérieur offertes par les API tamponnées; par exemple la méthode BufferedReader.readLine().

Cependant, si vous souhaitez uniquement effectuer des lectures de bloc volumineuses à l'aide des méthodes read(byte[]) et/ou read(byte[], int, int), le fait d'encapsuler le InputStream dans un BufferedInputStream ne pas d'aide.

(En réponse au commentaire de @Peter Tillman sur sa propre réponse, les cas d'utilisation de lecture de bloc représentent certainement plus de 0,1% des utilisations des classes InputStream !! Cependant, il a raison dans le sens où il est généralement - inoffensif pour utiliser une API tamponnée lorsque vous n'en avez pas besoin.)

34
Stephen C

Je ne le ferais pas, je le laisserais au niveau d'abstraction le plus élevé possible. Si vous ne comptez pas utiliser les capacités de marquage et de réinitialisation d'un BufferedStream, pourquoi vous embêter à en faire un emballage?

Si un consommateur en a besoin, il est préférable de l'envelopper.

6
Peter Tillemans

Vous n'aurez peut-être pas toujours besoin de mise en mémoire tampon, donc, pour cela, la réponse serait non, dans certains cas, c'est juste une surcharge.

Il y a une autre raison pour laquelle c'est "Non" et cela peut être plus grave. BufferedInputStream (ou BufferedReader) peut provoquer des échecs imprévisibles lorsqu'il est utilisé avec un socket réseau lorsque vous avez également activé un délai d'expiration sur le socket. Le délai d'attente peut se produire lors de la lecture d'un paquet. Vous ne pourrez plus accéder aux données qui ont été transférées à ce point - même si vous saviez qu'il y avait un nombre d'octets différent de zéro (voir Java.net.SocketTimeoutException Qui est une sous-classe de Java.io.InterruptedIOException a donc bytesTransferred variable disponible).

Si vous vous demandez comment un délai d'attente de socket peut se produire pendant la lecture, pensez simplement à appeler la méthode read(bytes[]) et le paquet d'origine qui contient le message a fini par être divisé, mais l'un des paquets partiels est retardé au-delà du délai d'attente ( ou la partie restante du délai). Cela peut se produire plus fréquemment lorsqu'il est à nouveau enveloppé dans quelque chose qui implémente Java.io.DataInput (L'une des lectures pour les valeurs à plusieurs octets, comme readLong() ou readFully() ou la fonction BufferedReader.readLine() méthode.

Notez que Java.io.DataInputStream Est également un mauvais candidat pour les flux de socket qui ont un délai d'attente car il ne se comporte pas bien non plus avec des exceptions de délai d'attente.

2
Kevin Brock

Cela dépend également de la façon dont vous allez lire dans InputStream. Si vous allez le lire un caractère/octet à la fois (c'est-à-dire read ()), le BufferedInputStream réduira vos frais généraux en faisant des lectures en bloc en votre nom. Si vous allez le lire dans un tableau d'octets/caractères 4k ou 8k un bloc à la fois, le BuffredInputStream ne vous sera probablement pas bénéfique.

0
Paul Jowett