Comment puis-je lire un InputStream
dans un tableau d'octets ?
Pour l'envie d'écrire 4 lignes de code, vous pensez que l'importation d'une dépendance tierce partie vaut la peine ?
Comment puis-je lire un InputStream
dans un tableau d'octets ?
Vous pouvez utiliser Apache Commons IO pour gérer cette tâche et d'autres similaires.
En IOUtils
possède une méthode statique pour lire un InputStream
et renvoyer un byte[]
.
InputStream is;
byte[] bytes = IOUtils.toByteArray(is);
En interne, cela crée un ByteArrayOutputStream
et copie les octets sur la sortie, puis appelle toByteArray()
. Il traite les gros fichiers en copiant les octets par blocs de 4KiB.
Pour l'envie d'écrire 4 lignes de code, vous pensez que l'importation d'une dépendance tierce partie vaut la peine ?
S'il existe une bibliothèque qui répond à cette exigence, qui traite le traitement des gros fichiers et qui est bien testée, la question est sûrement de savoir pourquoi je l'écrirais moi-même. Le jar ne fait que 107 Ko et si vous avez besoin d'une méthode, il est probable que vous en utilisiez d'autres.
@oxbow_lakes : considérant la quantité stupéfiante de mauvais implémentations de cette fonctionnalité que j'ai vues dans ma vie de développeur, je pense que oui c'est très Cela vaut vraiment la peine de dépendre de l'extérieur pour bien faire les choses.
Vous devez lire chaque octet de votre InputStream
et l'écrire dans un ByteArrayOutputStream
.
Vous pouvez ensuite récupérer le tableau d'octets sous-jacent en appelant toByteArray()
:
InputStream is = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
return buffer.toByteArray();
Qu'en est-il de la taille des byte[] nouvellement créés. Pourquoi est-elle de 16384 ? Comment puis-je déterminer la taille exacte ? Merci beaucoup.
16384 est un choix assez arbitraire bien que j'ai tendance à favoriser les puissances de 2 pour augmenter les chances que le tableau s'aligne sur les limites des mots. La réponse de pihentagy montre comment vous pouvez éviter d'utiliser un tampon intermédiaire, mais plutôt allouer un tableau de la taille correcte. A moins que vous n'ayez affaire à de gros fichiers, je préfère personnellement le code ci-dessus, qui est plus élégant et peut être utilisé pour les InputStreams où le nombre d'octets à lire n'est pas connu à l'avance.
@Adamski La création d'un tableau d'octets n'est-elle pas beaucoup plus grande que ce que vous attendez des données dans le flux, ne gaspille-t-elle pas la mémoire ?
Utilisez la fonction DataInputStream
et son readFully
Méthode (existe depuis au moins Java 1.4) :
...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...
Il existe d'autres variantes de cette méthode, mais je l'utilise tout le temps pour ce cas d'utilisation.
+1 pour l'utilisation des bibliothèques standard au lieu d'une dépendance d'une tierce partie. Malheureusement, cela ne fonctionne pas pour moi car je ne connais pas la longueur du flux en amont.
Qu'est-ce que imgFile ? Cela ne peut pas être un InputStream, qui était censé être l'entrée de cette méthode.
@janus c'est un "fichier". cette méthode ne fonctionne que si vous connaissez la longueur du fichier ou le nombre d'octets à lire.
Si vous utilisez Google Guava il suffira d'utiliser ByteStreams
:
byte[] bytes = ByteStreams.toByteArray(inputStream);
Avez-vous vraiment besoin de l'image comme byte[]
? Qu'attendez-vous exactement de la byte[]
- le contenu complet d'un fichier d'image, codé dans n'importe quel format du fichier d'image, ou les valeurs de pixels RVB ?
D'autres réponses ici vous montrent comment lire un fichier dans une byte[]
. Votre byte[]
contiendra le contenu exact du fichier, et vous devrez le décoder pour faire quoi que ce soit avec les données de l'image.
L'API standard de Java pour lire (et écrire) des images est l'API ImageIO, que vous trouverez dans le paquetage javax.imageio
. Vous pouvez lire une image à partir d'un fichier avec une seule ligne de code :
BufferedImage image = ImageIO.read(new File("image.jpg"));
Cela vous donnera un BufferedImage
et non un byte[]
. Pour accéder aux données de l'image, vous pouvez appeler getRaster()
sur le BufferedImage
. Cela vous donnera un Raster
qui dispose de méthodes pour accéder aux données des pixels (il a plusieurs objets getPixel()
/ getPixels()
méthodes).
Consultez la documentation de l'API pour javax.imageio.ImageIO
, java.awt.image.BufferedImage
, java.awt.image.Raster
etc.
ImageIO supporte par défaut un certain nombre de formats d'images : JPEG, PNG, BMP, WBMP et GIF. Il est possible d'ajouter le support d'autres formats (vous aurez besoin d'un plug-in qui implémente l'interface du fournisseur de services ImageIO).
Voir aussi le tutoriel suivant : Travailler avec des images
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
18 votes
Voir l'inverse : byte[] to InputStream ici : stackoverflow.com/questions/2091454/