En interne, cela crée un ByteArrayOutputStreamet copie les octets dans la sortie, puis appelle toByteArray(). Il gère les fichiers volumineux en copiant les octets dans des blocs de 4 Ko.
Par manque d'écriture de 4 lignes de code, vous pensez que l'importation d'une dépendance tierce vaut la peine?
oxbow_lakes
217
S'il existe une bibliothèque qui gère l'exigence, traite le traitement des fichiers volumineux et est bien testée, la question est sûrement pourquoi je l'écrirais moi-même? Le pot ne fait que 107 Ko et si vous avez besoin d'une méthode, vous en utiliserez probablement d'autres
Rich Seller
242
@oxbow_lakes: compte tenu de la quantité phénoménale de mauvaises implémentations de cette fonctionnalité que je l' ai vu dans ma vie de développeur, je pense que oui , il est très bien vaut la dépendance extérieure pour obtenir ce droit.
Joachim Sauer
17
Pourquoi ne pas aller voir les trucs communs Apache comme FastArrayListou leurs cartes de référence douces et faibles et revenir me dire à quel point cette bibliothèque est "bien testée". C'est un tas d'ordures
oxbow_lakes
87
En plus d'Apache commons-io, consultez la classe ByteStreams de Google Guava . InputStream is;byte[] filedata=ByteStreams.toByteArray(is);
michaelok
446
Vous devez lire chaque octet de votre InputStreamet l'écrire dans a ByteArrayOutputStream.
Vous pouvez ensuite récupérer le tableau d'octets sous-jacent en appelant toByteArray():
InputStream is =...ByteArrayOutputStream buffer =newByteArrayOutputStream();int nRead;byte[] data =newbyte[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 de l'octet nouvellement créé []. Pourquoi est-ce 16384? Comment pourrais-je déterminer la bonne taille exacte? Merci beaucoup.
Ondrej Bozek
6
16384 est un choix assez arbitraire même si j'ai tendance à privilégier les puissances de 2 pour augmenter les chances d'alignement du tableau avec 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 bonne taille. Sauf si vous avez affaire à de gros fichiers, je préfère personnellement le code ci-dessus, qui est plus élégant et peut être utilisé pour InputStreams où le nombre d'octets à lire n'est pas connu à l'avance.
Adamski
@Adamski La création d'un tableau d'octets n'est-elle pas beaucoup plus importante que ce que vous attendez des données dans le flux, gaspillez-vous la mémoire?
Paul Brewczynski
@bluesm: Oui, c'est exact. Cependant, dans mon exemple, le tableau d'octets n'est que de 16 Ko et si petit par rapport aux normes d'aujourd'hui. Bien entendu, cette mémoire sera à nouveau libérée par la suite.
Adamski
5
@Adamski Beaucoup de matériel d'infrastructure, de serveurs Web et de composants de la couche OS utilisent des tampons 4K pour déplacer les données, c'est donc la raison du nombre exact, mais l'essentiel est que vous obtenez une telle amélioration des performances en passant par 4K qu'il est généralement considéré comme un gaspillage de mémoire. Je suppose que c'est toujours vrai, car c'est une connaissance vieille de dix ans que j'avais!
312
Enfin, après vingt ans, il existe une solution simple sans avoir besoin d'une bibliothèque tierce, grâce à Java 9 :
+1 pour l'utilisation des bibliothèques standard au lieu d'une dépendance tierce. Malheureusement, cela ne fonctionne pas pour moi car je ne connais pas la longueur du flux à l'avance.
Andrew Spencer
2
qu'est-ce que imgFile? Ce ne peut pas être un InputStream, qui était censé être l'entrée de cette méthode
Janus Troelsen
4
@janus c'est un "Fichier". cette façon ne fonctionne que si vous connaissez la longueur du fichier ou le nombre d'octets à lire.
dermoritz
5
Chose intéressante, mais vous devez connaître la longueur exacte du (partie du) flux à lire. De plus, la classe DataInputStreamest principalement utilisée pour lire les types primaires (Longs, Shorts, Chars ...) à partir d'un flux, nous pouvons donc voir cette utilisation comme une mauvaise utilisation de la classe.
Olivier Faucheux
17
Si vous connaissez déjà la longueur des données à lire dans le flux, ce n'est pas mieux que InputStream.read.
Ramassage Logan du
119
Si vous utilisez google goyave , ce sera aussi simple que:
Comme la plupart des autres, je voulais éviter d'utiliser une bibliothèque tierce pour quelque chose de si simple, mais Java 9 n'est pas une option pour le moment ... heureusement, j'utilisais déjà Spring.
scottysseus
42
publicstaticbyte[] getBytesFromInputStream(InputStream is)throwsIOException{ByteArrayOutputStream os =newByteArrayOutputStream();byte[] buffer =newbyte[0xFFFF];for(int len = is.read(buffer); len !=-1; len = is.read(buffer)){
os.write(buffer,0, len);}return os.toByteArray();}
C'est un exemple et à ce titre, la brièveté est à l'ordre du jour. Renvoyer également null ici serait le bon choix dans certains cas (bien que dans un environnement de production, vous auriez également une gestion et une documentation des exceptions appropriées).
11
Je comprends la brièveté dans un exemple, mais pourquoi ne pas simplement faire en sorte que l'exemple de méthode lance IOException plutôt que de l'avaler et de renvoyer une valeur vide de sens?
pendor
4
j'ai pris la liberté de passer de 'return null' à 'throw IOException'
kritzikratzi
3
Try-with-resources n'est pas nécessaire ici, car ByteArrayOutputStream # close () ne fait rien. (ByteArrayOutputStream # flush () n'est pas nécessaire et ne fait rien de trop.)
Version Kotlin (lorsque Java 9+ n'est pas accessible):
@Throws(IOException::class)
fun InputStream.readAllBytes():ByteArray{
val bufLen =4*0x400// 4KB
val buf =ByteArray(bufLen)
var readLen:Int=0ByteArrayOutputStream().use { o ->this.use { i ->while(i.read(buf,0, bufLen).also { readLen = it }!=-1)
o.write(buf,0, readLen)}return o.toByteArray()}}
Cela ne signifie-t-il pas qu'à un moment donné, vous auriez le double de la mémoire utilisée, car vous disposez à la fois du tampon et du tableau d'octets? N'y a-t-il pas un moyen d'envoyer les octets directement au tableau d'octets de sortie?
développeur Android
@androiddeveloper; Je suis désolé. Je ne connais pas la réponse! Mais je ne pense pas. Je pense que cette façon (en utilisant un tampon) est une manière optimisée.
Mir-Ismaili
J'ai vérifié et c'est le cas, mais il semble que c'est la seule solution que vous pouvez choisir lorsque vous ne connaissez pas la taille. Si vous connaissez déjà la taille, vous pouvez créer directement le tableau d'octets avec la taille donnée et le remplir. Ainsi, vous utilisez une fonction qui obtiendra un paramètre de la taille de l'octet, et si elle est valide, utilisez-la pour créer et remplir directement le tableau d'octets, sans créer d'autre grand objet.
développeur Android
@androiddeveloper; Merci pour ton information. Je ne les connaissais pas.
Mir-Ismaili
19
Avez-vous vraiment besoin de l'image en tant que byte[]? Qu'attendez-vous exactement dans le byte[]- le contenu complet d'un fichier image, encodé dans le format dans lequel le fichier image est, ou les valeurs de pixels RVB?
D'autres réponses ici vous montrent comment lire un fichier dans un fichier 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 d'image.
L'API standard de Java pour la lecture (et l'écriture) d'images est l'API ImageIO, que vous pouvez trouver dans le package javax.imageio. Vous pouvez lire une image à partir d'un fichier avec une seule ligne de code:
Cela vous donnera un BufferedImage, pas un byte[]. Pour accéder aux données d'image, vous pouvez appeler getRaster()le BufferedImage. Cela vous donnera un Rasterobjet, qui a des méthodes pour accéder aux données de pixel (il en a plusieurs getPixel()/ getPixels()méthodes).
Lookup la documentation de l' API pour javax.imageio.ImageIO, java.awt.image.BufferedImage, java.awt.image.Rasteretc.
ImageIO prend en charge un certain nombre de formats d'image par défaut: JPEG, PNG, BMP, WBMP et GIF. Il est possible d'ajouter la prise en charge de plusieurs formats (vous auriez besoin d'un plug-in qui implémente l'interface du fournisseur de services ImageIO).
Par exemple, que se passe-t-il si le tableau d'octets est trop grand, ce qui pourrait provoquer un MOO pour le tas? Existe-t-il une solution similaire qui utilisera JNI pour stocker les octets, et plus tard, nous pourrons utiliser inputStream à partir des données qui y sont stockées (sorte de cache temporaire)?
développeur Android
14
Si vous ne souhaitez pas utiliser la bibliothèque Apache commons-io, cet extrait est extrait de la classe sun.misc.IOUtils. C'est presque deux fois plus rapide que l'implémentation courante utilisant ByteBuffers:
C'est un peu une solution bizarre, la longueur est une limite supérieure sur la longueur du tableau. Si vous connaissez la longueur, tout ce dont vous avez besoin est: octet [] sortie = nouvel octet [longueur]; is.read (sortie); (mais voir ma réponse)
Luke Hutchison
@ luke-hutchison comme je l'ai dit, c'est la solution de sun.misc.IOUtils. Dans les cas les plus courants, vous ne connaissez pas la taille d'un InputStream à l'avance, donc si (length == -1) length = Integer.MAX_VALUE; s'applique. Cette solution fonctionne, même si la longueur donnée est supérieure à la longueur de InputStream.
Kristian Kraljic
@LukeHutchison Si vous connaissez la longueur, vous pouvez le gérer avec quelques lignes. Si vous regardez chaque réponse, tout le monde se plaint que la longueur n'est pas connue. Enfin une réponse qui est standard, peut être utilisée avec Java 7 Android, et ne nécessite aucune bibliothèque externe.
Csaba Toth du
11
ByteArrayOutputStream out =newByteArrayOutputStream();byte[] buffer =newbyte[1024];while(true){int r = in.read(buffer);if(r ==-1)break;
out.write(buffer,0, r);}byte[] ret = out.toByteArray();
// Returns the contents of the file in a byte array.publicstaticbyte[] getBytesFromFile(File file)throwsIOException{InputStream is =newFileInputStream(file);// Get the size of the filelong length = file.length();// You cannot create an array using a long type.// It needs to be an int type.// Before converting to an int type, check// to ensure that file is not larger than Integer.MAX_VALUE.if(length >Integer.MAX_VALUE){// File is too large}// Create the byte array to hold the databyte[] bytes =newbyte[(int)length];// Read in the bytesint offset =0;int numRead =0;while(offset < bytes.length
&&(numRead=is.read(bytes, offset, bytes.length-offset))>=0){
offset += numRead;}// Ensure all the bytes have been read inif(offset < bytes.length){thrownewIOException("Could not completely read file "+file.getName());}// Close the input stream and return bytes
is.close();return bytes;}
InputStream is ...ByteArrayOutputStream bos =newByteArrayOutputStream();int next = in.read();while(next >-1){
bos.write(next);
next = in.read();}
bos.flush();byte[] result = bos.toByteArray();
bos.close();
Cependant, le système d'exploitation a déjà suffisamment de tampons pour que cela ne soit pas un gros problème pour les fichiers plus petits. Ce n'est pas comme si la tête du disque dur lisait chaque octet séparément (un disque dur est une plaque de verre tournante avec des informations codées magnétiques dessus, un peu comme cette icône bizarre que nous utilisons pour enregistrer les données: P).
Maarten Bodewes
6
@Maarten Bodewes: la plupart des appareils ont une sorte de transfert de bloc, donc pas chaque lecture () provoquera un accès réel à l'appareil, mais avoir un appel OS par octet est déjà suffisant pour tuer les performances. Bien que l'encapsulation InputStreamdans un BufferedInputStreamavant ce code réduise les appels du système d'exploitation et atténue considérablement les inconvénients de performances, ce code effectuera toujours un travail de copie manuelle inutile d'un tampon à un autre.
Quelle est la différence entre ceci et ce InputStram.readAllBytes()qui est à une ligne?
Slava Semushin
2
Je sais qu'il est trop tard mais ici je pense que c'est une solution plus propre et plus lisible ...
/**
* method converts {@link InputStream} Object into byte[] array.
*
* @param stream the {@link InputStream} Object.
* @return the byte[] array representation of received {@link InputStream} Object.
* @throws IOException if an error occurs.
*/publicstaticbyte[] streamToByteArray(InputStream stream)throwsIOException{byte[] buffer =newbyte[1024];ByteArrayOutputStream os =newByteArrayOutputStream();int line =0;// read bytes from stream, and store them in bufferwhile((line = stream.read(buffer))!=-1){// Writes bytes from byte array (buffer) into output stream.
os.write(buffer,0, line);}
stream.close();
os.flush();
os.close();return os.toByteArray();}
Ce n'est pas seulement \rque cela pourrait être un problème. Cette méthode convertit les octets en caractères et inversement (en utilisant le jeu de caractères par défaut pour InputStreamReader). Tous les octets qui ne sont pas valides dans le codage de caractères par défaut (disons -1 pour UTF-8 sous Linux) seront corrompus, ce qui pourrait même changer le nombre d'octets.
seanf
On dirait que c'est une bonne réponse, mais orientée texte. Méfiez-vous de l'acheteur.
Wheezil
1
J'ai essayé de modifier la réponse de @ numan avec un correctif pour écrire des données de poubelle, mais la modification a été rejetée. Bien que ce court morceau de code ne soit rien de brillant, je ne vois pas d'autre meilleure réponse. Voici ce qui me semble le plus logique:
ByteArrayOutputStream out =newByteArrayOutputStream();byte[] buffer =newbyte[1024];// you can configure the buffer sizeint length;while((length = in.read(buffer))!=-1) out.write(buffer,0, length);//copy streams
in.close();// call this in a finally blockbyte[] result = out.toByteArray();
btw ByteArrayOutputStream n'a pas besoin d'être fermé. essayez / finalement les constructions omises pour la lisibilité
Consultez la InputStream.available()documentation:
Il est particulièrement important de réaliser que vous ne devez pas utiliser cette méthode pour dimensionner un conteneur et supposer que vous pouvez lire l'intégralité du flux sans avoir besoin de redimensionner le conteneur. Ces appelants devraient probablement écrire tout ce qu'ils lisent dans un ByteArrayOutputStream et le convertir en un tableau d'octets. Alternativement, si vous lisez un fichier, File.length renvoie la longueur actuelle du fichier (bien que supposer que la longueur du fichier ne puisse pas changer peut être incorrect, la lecture d'un fichier est intrinsèquement racée).
Enveloppez-le dans un DataInputStream si cela est hors de la table pour une raison quelconque, utilisez simplement read pour marteler dessus jusqu'à ce qu'il vous donne un -1 ou le bloc entier que vous avez demandé.
Nous constatons un certain retard pour quelques transactions AWS, lors de la conversion de l'objet S3 en ByteArray.
Remarque: l'objet S3 est un document PDF (la taille maximale est de 3 Mo).
Nous utilisons l'option # 1 (org.apache.commons.io.IOUtils) pour convertir l'objet S3 en ByteArray. Nous avons remarqué que S3 fournit la méthode IOUtils inbuild pour convertir l'objet S3 en ByteArray, nous vous demandons de confirmer quelle est la meilleure façon de convertir l'objet S3 en ByteArray pour éviter le retard.
Option 1:
import org.apache.commons.io.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Option 2:
import com.amazonaws.util.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Faites-moi également savoir si nous avons une autre meilleure façon de convertir l'objet s3 en bytearray
L'autre cas pour obtenir un tableau d'octets correct via le flux, après l'envoi de la demande au serveur et l'attente de la réponse.
/**
* Begin setup TCP connection to PC app
* to open integrate connection between mobile app and pc app (or mobile app)
*/
mSocket =newSocket(IP, port);// mSocket.setSoTimeout(30000);DataOutputStream mDos =newDataOutputStream(mSocket.getOutputStream());String str ="MobileRequest#"+ params[0]+"#<EOF>";
mDos.write(str.getBytes());try{Thread.sleep(1000);}catch(InterruptedException e){
e.printStackTrace();}/* Since data are accepted as byte, all of them will be collected in the
following byte array which initialised with accepted data length. */DataInputStream mDis =newDataInputStream(mSocket.getInputStream());byte[] data =newbyte[mDis.available()];// Collecting data into byte arrayfor(int i =0; i < data.length; i++)
data[i]= mDis.readByte();// Converting collected data in byte array into String.String RESPONSE =newString(data);
Vous faites une copie supplémentaire si vous utilisez ByteArrayOutputStream. Si vous connaissez la longueur du flux avant de commencer à le lire (par exemple, InputStream est en fait un FileInputStream, et vous pouvez appeler file.length () sur le fichier, ou InputStream est une entrée de fichier zip InputStream, et vous pouvez appeler zipEntry. length ()), il est alors préférable d'écrire directement dans le tableau d'octets [] - il utilise la moitié de la mémoire et fait gagner du temps.
// Read the file contents into a byte[] arraybyte[] buf =newbyte[inputStreamLength];int bytesRead =Math.max(0, inputStream.read(buf));// If needed: for safety, truncate the array if the file may somehow get// truncated during the read operationbyte[] contents = bytesRead == inputStreamLength ? buf
:Arrays.copyOf(buf, bytesRead);
NB la dernière ligne ci-dessus traite des fichiers qui sont tronqués pendant la lecture du flux, si vous avez besoin de gérer cette possibilité, mais si le fichier s'allonge pendant la lecture du flux, le contenu du tableau d'octets [] ne sera pas allongé pour inclure le nouveau contenu du fichier, le tableau sera simplement tronqué à l'ancienne longueur inputStreamLength .
Ajoutez une explication avec la réponse pour savoir comment cette réponse aide OP à résoudre le problème actuel
ρяσѕρєя K
0
Voici ma version copier-coller:
@SuppressWarnings("empty-statement")publicstaticbyte[] inputStreamToByte(InputStream is)throwsIOException{if(is ==null){returnnull;}// Define a size if you have an idea of it.ByteArrayOutputStream r =newByteArrayOutputStream(2048);byte[] read =newbyte[512];// Your buffer size.for(int i;-1!=(i = is.read(read)); r.write(read,0, i));
is.close();return r.toByteArray();}
Bien que cet extrait de code puisse résoudre la question, y compris une explication aide vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondrez à la question pour les lecteurs à l'avenir, et ces personnes pourraient ne pas connaître les raisons de votre suggestion de code.
Ferrybig
0
Java 7 et versions ultérieures:
import sun.misc.IOUtils;...InputStream in =...;byte[] buf =IOUtils.readFully(in,-1,false);
sun.misc.IOUtilsn'est pas «Java 7». Il s'agit d'une classe propriétaire spécifique à l'implémentation qui peut ne pas être présente dans d'autres implémentations JRE et peut disparaître sans avertissement dans l'une des prochaines versions.
Solution dans Kotlin (fonctionnera également en Java, bien sûr), qui comprend les deux cas où vous connaissez la taille ou non:
fun InputStream.readBytesWithSize(size:Long):ByteArray?{return when {
size <0L->this.readBytes()
size ==0L->ByteArray(0)
size >Int.MAX_VALUE ->nullelse->{
val sizeInt = size.toInt()
val result =ByteArray(sizeInt)
readBytesIntoByteArray(result, sizeInt)
result
}}}
fun InputStream.readBytesIntoByteArray(byteArray:ByteArray,bytesToRead:Int=byteArray.size){
var offset =0while(true){
val read =this.read(byteArray, offset, bytesToRead - offset)if(read ==-1)break
offset += read
if(offset >= bytesToRead)break}}
Si vous connaissez la taille, cela vous évite d'avoir le double de la mémoire utilisée par rapport aux autres solutions (dans un bref instant, mais pourrait tout de même être utile). C'est parce que vous devez lire l'intégralité du flux à la fin, puis le convertir en un tableau d'octets (similaire à ArrayList que vous convertissez en un simple tableau).
Donc, si vous êtes sur Android, par exemple, et que vous avez un Uri à gérer, vous pouvez essayer d'obtenir la taille en utilisant ceci:
fun getStreamLengthFromUri(context:Context, uri:Uri):Long{
context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.SIZE),null,null,null)?.use {if(!it.moveToNext())return@use
val fileSize = it.getLong(it.getColumnIndex(MediaStore.MediaColumns.SIZE))if(fileSize >0)return fileSize
}//if you wish, you can also get the file-path from the uri here, and then try to get its size, using this: https://stackoverflow.com/a/61835665/878126FileUtilEx.getFilePathFromUri(context, uri,false)?.use {
val file = it.file
val fileSize = file.length()if(fileSize >0)return fileSize
}
context.contentResolver.openInputStream(uri)?.use { inputStream ->if(inputStream is FileInputStream)return inputStream.channel.size()else{
var bytesCount =0Lwhile(true){
val available = inputStream.available()if(available ==0)break
val skip = inputStream.skip(available.toLong())if(skip <0)break
bytesCount += skip
}if(bytesCount >0L)return bytesCount
}}return-1L}
/*InputStream class_InputStream = null;
I am reading class from DB
class_InputStream = rs.getBinaryStream(1);
Your Input stream could be from any source
*/int thisLine;ByteArrayOutputStream bos =newByteArrayOutputStream();while((thisLine = class_InputStream.read())!=-1){
bos.write(thisLine);}
bos.flush();byte[] yourBytes = bos.toByteArray();/*Don't forget in the finally block to close ByteArrayOutputStream & InputStream
In my case the IS is from resultset so just closing the rs will do it*/if(bos !=null){
bos.close();}
Fermer et rincer les bos est un gaspillage de clics sur le clavier. La fermeture du flux d'entrée est plus susceptible de vous aider. La lecture d'un octet à la fois est inefficace. Voir la réponse de numan.
Réponses:
Vous pouvez utiliser Apache Commons IO pour gérer cela et des tâches similaires.
Le
IOUtils
type a une méthode statique pour lireInputStream
et renvoyer unbyte[]
.En interne, cela crée un
ByteArrayOutputStream
et copie les octets dans la sortie, puis appelletoByteArray()
. Il gère les fichiers volumineux en copiant les octets dans des blocs de 4 Ko.la source
FastArrayList
ou leurs cartes de référence douces et faibles et revenir me dire à quel point cette bibliothèque est "bien testée". C'est un tas d'orduresInputStream is;
byte[] filedata=ByteStreams.toByteArray(is);
Vous devez lire chaque octet de votre
InputStream
et l'écrire dans aByteArrayOutputStream
.Vous pouvez ensuite récupérer le tableau d'octets sous-jacent en appelant
toByteArray()
:la source
Enfin, après vingt ans, il existe une solution simple sans avoir besoin d'une bibliothèque tierce, grâce à Java 9 :
Notez également les méthodes pratiques
readNBytes(byte[] b, int off, int len)
et latransferTo(OutputStream)
réponse aux besoins récurrents.la source
Utilisez le Java vanilla
DataInputStream
et sareadFully
méthode (existe depuis au moins Java 1.4):Il existe d'autres variantes de cette méthode, mais je l'utilise tout le temps pour ce cas d'utilisation.
la source
DataInputStream
est principalement utilisée pour lire les types primaires (Longs, Shorts, Chars ...) à partir d'un flux, nous pouvons donc voir cette utilisation comme une mauvaise utilisation de la classe.InputStream.read
.Si vous utilisez google goyave , ce sera aussi simple que:
la source
ByteStreams
est annoté avec@Beta
Comme toujours, le framework Spring (Spring-core depuis 3.2.2) a quelque chose pour vous:
StreamUtils.copyToByteArray()
la source
la source
Solution sûre (avec capacité de
close
flux correctement):Version Java 9+:
Version Java 8:
Version Kotlin (lorsque Java 9+ n'est pas accessible):
Pour éviter l'imbrication,
use
voir ici .la source
Avez-vous vraiment besoin de l'image en tant que
byte[]
? Qu'attendez-vous exactement dans lebyte[]
- le contenu complet d'un fichier image, encodé dans le format dans lequel le fichier image est, ou les valeurs de pixels RVB?D'autres réponses ici vous montrent comment lire un fichier dans un fichier
byte[]
. Votrebyte[]
contiendra le contenu exact du fichier et vous devrez le décoder pour faire quoi que ce soit avec les données d'image.L'API standard de Java pour la lecture (et l'écriture) d'images est l'API ImageIO, que vous pouvez trouver dans le package
javax.imageio
. Vous pouvez lire une image à partir d'un fichier avec une seule ligne de code:Cela vous donnera un
BufferedImage
, pas unbyte[]
. Pour accéder aux données d'image, vous pouvez appelergetRaster()
leBufferedImage
. Cela vous donnera unRaster
objet, qui a des méthodes pour accéder aux données de pixel (il en a plusieursgetPixel()
/getPixels()
méthodes).Lookup la documentation de l' API pour
javax.imageio.ImageIO
,java.awt.image.BufferedImage
,java.awt.image.Raster
etc.ImageIO prend en charge un certain nombre de formats d'image par défaut: JPEG, PNG, BMP, WBMP et GIF. Il est possible d'ajouter la prise en charge de plusieurs formats (vous auriez besoin d'un plug-in qui implémente l'interface du fournisseur de services ImageIO).
Voir également le didacticiel suivant: Utilisation des images
la source
Dans le cas où quelqu'un est toujours à la recherche d'une solution sans dépendance et si vous avez un fichier .
la source
Si vous ne souhaitez pas utiliser la bibliothèque Apache commons-io, cet extrait est extrait de la classe sun.misc.IOUtils. C'est presque deux fois plus rapide que l'implémentation courante utilisant ByteBuffers:
la source
la source
@Adamski: Vous pouvez éviter complètement le tampon.
Code copié depuis http://www.exampledepot.com/egs/java.io/File2ByteArray.html (Oui, il est très verbeux, mais nécessite la moitié de la taille de la mémoire comme l'autre solution.)
la source
is.close()
sioffset < bytes.length
ouInputStream
ne sera pas fermé si cette exception est levée.la source
InputStream
dans unBufferedInputStream
avant ce code réduise les appels du système d'exploitation et atténue considérablement les inconvénients de performances, ce code effectuera toujours un travail de copie manuelle inutile d'un tampon à un autre.Java 9 vous donnera enfin une belle méthode:
la source
InputStram.readAllBytes()
qui est à une ligne?Je sais qu'il est trop tard mais ici je pense que c'est une solution plus propre et plus lisible ...
la source
Java 8 way (merci à BufferedReader et Adam Bien )
Notez que cette solution efface le retour chariot ('\ r') et peut être inappropriée.
la source
String
. OP demandebyte[]
.\r
que cela pourrait être un problème. Cette méthode convertit les octets en caractères et inversement (en utilisant le jeu de caractères par défaut pour InputStreamReader). Tous les octets qui ne sont pas valides dans le codage de caractères par défaut (disons -1 pour UTF-8 sous Linux) seront corrompus, ce qui pourrait même changer le nombre d'octets.J'ai essayé de modifier la réponse de @ numan avec un correctif pour écrire des données de poubelle, mais la modification a été rejetée. Bien que ce court morceau de code ne soit rien de brillant, je ne vois pas d'autre meilleure réponse. Voici ce qui me semble le plus logique:
btw ByteArrayOutputStream n'a pas besoin d'être fermé. essayez / finalement les constructions omises pour la lisibilité
la source
Consultez la
InputStream.available()
documentation:la source
Enveloppez-le dans un DataInputStream si cela est hors de la table pour une raison quelconque, utilisez simplement read pour marteler dessus jusqu'à ce qu'il vous donne un -1 ou le bloc entier que vous avez demandé.
la source
Nous constatons un certain retard pour quelques transactions AWS, lors de la conversion de l'objet S3 en ByteArray.
Remarque: l'objet S3 est un document PDF (la taille maximale est de 3 Mo).
Nous utilisons l'option # 1 (org.apache.commons.io.IOUtils) pour convertir l'objet S3 en ByteArray. Nous avons remarqué que S3 fournit la méthode IOUtils inbuild pour convertir l'objet S3 en ByteArray, nous vous demandons de confirmer quelle est la meilleure façon de convertir l'objet S3 en ByteArray pour éviter le retard.
Option 1:
Option 2:
Faites-moi également savoir si nous avons une autre meilleure façon de convertir l'objet s3 en bytearray
la source
L'autre cas pour obtenir un tableau d'octets correct via le flux, après l'envoi de la demande au serveur et l'attente de la réponse.
la source
Vous faites une copie supplémentaire si vous utilisez ByteArrayOutputStream. Si vous connaissez la longueur du flux avant de commencer à le lire (par exemple, InputStream est en fait un FileInputStream, et vous pouvez appeler file.length () sur le fichier, ou InputStream est une entrée de fichier zip InputStream, et vous pouvez appeler zipEntry. length ()), il est alors préférable d'écrire directement dans le tableau d'octets [] - il utilise la moitié de la mémoire et fait gagner du temps.
NB la dernière ligne ci-dessus traite des fichiers qui sont tronqués pendant la lecture du flux, si vous avez besoin de gérer cette possibilité, mais si le fichier s'allonge pendant la lecture du flux, le contenu du tableau d'octets [] ne sera pas allongé pour inclure le nouveau contenu du fichier, le tableau sera simplement tronqué à l'ancienne longueur inputStreamLength .
la source
J'utilise ça.
la source
Voici ma version copier-coller:
la source
Java 7 et versions ultérieures:
la source
sun.misc.IOUtils
n'est pas «Java 7». Il s'agit d'une classe propriétaire spécifique à l'implémentation qui peut ne pas être présente dans d'autres implémentations JRE et peut disparaître sans avertissement dans l'une des prochaines versions.Vous pouvez essayer Cactoos :
la source
Voici une version optimisée, qui essaie d'éviter autant que possible de copier des octets de données:
la source
Solution dans Kotlin (fonctionnera également en Java, bien sûr), qui comprend les deux cas où vous connaissez la taille ou non:
Si vous connaissez la taille, cela vous évite d'avoir le double de la mémoire utilisée par rapport aux autres solutions (dans un bref instant, mais pourrait tout de même être utile). C'est parce que vous devez lire l'intégralité du flux à la fin, puis le convertir en un tableau d'octets (similaire à ArrayList que vous convertissez en un simple tableau).
Donc, si vous êtes sur Android, par exemple, et que vous avez un Uri à gérer, vous pouvez essayer d'obtenir la taille en utilisant ceci:
la source
la source