Convertir InputStream en tableau d'octets en Java
Comment lire un InputStream
entier dans un tableau d'octets?
30 réponses
vous pouvez utiliser Apache Commons IO pour gérer cette tâche et des tâches similaires.
le type IOUtils
a une méthode statique pour lire un InputStream
et retourner un byte[]
.
InputStream is;
byte[] bytes = IOUtils.toByteArray(is);
en interne cela crée un ByteArrayOutputStream
et copie les octets à la sortie, puis appelle toByteArray()
. Il gère les gros fichiers en copiant les octets en blocs de 4kib.
vous devez lire chaque octet de votre InputStream
et l'écrire à un ByteArrayOutputStream
. Vous pouvez ensuite récupérer le tableau byte sous-jacent en appelant toByteArray()
; par exemple
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);
}
buffer.flush();
return buffer.toByteArray();
enfin, après vingt ans, il y a une solution simple sans avoir besoin d'une bibliothèque tierce, grâce à Java 9 :
InputStream is;
…
byte[] array = is.readAllBytes();
noter également les méthodes de commodité readNBytes(byte[] b, int off, int len)
et transferTo(OutputStream)
répondre aux besoins récurrents.
si vous utilisez google guava , ce sera aussi simple que:
byte[] bytes = ByteStreams.toByteArray(inputStream);
utilisez la méthode Java DataInputStream
et sa méthode readFully
(existe depuis au moins Java 1.4):
...
byte[] imgDataBa = new byte[(int)imgFile.length()];
DataInputStream dataIs = new DataInputStream(new FileInputStream(imgFile));
dataIs.readFully(imgDataBa);
...
il y a d'autres saveurs de cette méthode, mais je l'utilise tout le temps pour ce cas d'utilisation.
public static byte[] getBytesFromInputStream(InputStream is) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
byte[] buffer = new byte[0xFFFF];
for (int len = is.read(buffer); len != -1; len = is.read(buffer)) {
os.write(buffer, 0, len);
}
return os.toByteArray();
}
comme toujours, aussi cadre de ressort (noyau de ressort depuis 3.2.2) a quelque chose pour vous: StreamUtils.copyToByteArray()
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 quelque format que le fichier image est, ou les valeurs de pixels RGB?
d'Autres réponses ici vous montrer comment lire un fichier dans un byte[]
. Votre byte[]
contiendra le contenu exact du fichier, et vous aurez besoin de le décoder pour faire quoi que ce soit avec les données de l'image.
Java standard API for reading (and writing) images est L'API ImageIO, que vous pouvez trouver dans le paquet 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
, pas un byte[]
. Pour obtenir les données d'image, vous pouvez appeler getRaster()
sur le BufferedImage
. Cela vous donnera un objet Raster
, qui a des méthodes pour accéder aux données des pixels (il a plusieurs méthodes getPixel()
/ getPixels()
).
rechercher la documentation de L'API pour javax.imageio.ImageIO
, java.awt.image.BufferedImage
, java.awt.image.Raster
etc.
ImageIO supporte un certain nombre de formats d'image par défaut: JPEG, PNG, BMP, WBMP et GIF. Il est possible d'ajouter le support pour plus de formats (vous avez besoin d'un plug-in qui implémente L'interface du fournisseur de services ImageIO).
voir aussi le tutoriel suivant: travailler avec les Images
si vous ne voulez pas utiliser la bibliothèque Apache commons-io, cet extrait est tiré du soleil.misc.Classe IOUtils. Il est presque deux fois plus rapide que l'implémentation commune en utilisant des ByteBuffers:
public static byte[] readFully(InputStream is, int length, boolean readAll)
throws IOException {
byte[] output = {};
if (length == -1) length = Integer.MAX_VALUE;
int pos = 0;
while (pos < length) {
int bytesToRead;
if (pos >= output.length) { // Only expand when there's no room
bytesToRead = Math.min(length - pos, output.length + 1024);
if (output.length < pos + bytesToRead) {
output = Arrays.copyOf(output, pos + bytesToRead);
}
} else {
bytesToRead = output.length - pos;
}
int cc = is.read(output, pos, bytesToRead);
if (cc < 0) {
if (readAll && length != Integer.MAX_VALUE) {
throw new EOFException("Detect premature EOF");
} else {
if (output.length != pos) {
output = Arrays.copyOf(output, pos);
}
break;
}
}
pos += cc;
}
return output;
}
dans le cas où quelqu'un est encore à la recherche d'une solution sans dépendance et si vous avez un fichier .
1) DataInputStream
byte[] data = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(data);
dis.close();
2) ByteArrayOutputStream
InputStream is = new FileInputStream(file);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[(int) file.length()];
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
3) RandomAccessFile
RandomAccessFile raf = new RandomAccessFile(file, "r");
byte[] data = new byte[(int) raf.length()];
raf.readFully(data);
@Adamski:vous pouvez éviter tout tampon.
code copié de http://www.exampledepot.com/egs/java.io/File2ByteArray.html (Oui, il est très verbeux, mais a besoin de la moitié de la taille de la mémoire que l'autre solution.)
// Returns the contents of the file in a byte array.
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long 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 data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int 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 in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
while (true) {
int r = in.read(buffer);
if (r == -1) break;
out.write(buffer, 0, r);
}
byte[] ret = out.toByteArray();
Input Stream is ...
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int next = in.read();
while (next > -1) {
bos.write(next);
next = in.read();
}
bos.flush();
byte[] result = bos.toByteArray();
bos.close();
Java 9 vous donnera enfin une belle méthode:
InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
je sais qu'il est trop tard, mais ici je pense que c'est une solution plus propre qui est 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.
*/
public static byte[] streamToByteArray(InputStream stream) throws IOException {
byte[] buffer = new byte[1024];
ByteArrayOutputStream os = new ByteArrayOutputStream();
int line = 0;
// read bytes from stream, and store them in buffer
while ((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();
}
j'ai essayé d'éditer la réponse de @numan avec un correctif pour écrire des données d'ordures mais l'édition a été rejetée. Bien que ce petit morceau de code ne soit rien de brillant, Je ne vois pas d'autre meilleure réponse. Voici ce qui a le plus de sens pour moi:
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024]; // you can configure the buffer size
int length;
while ((length = in.read(buffer)) != -1) out.write(buffer, 0, length); //copy streams
in.close(); // call this in a finally block
byte[] result = out.toByteArray();
btw ByteArrayOutputStream ne doit pas être fermé. try / finally constructions omitted for readability
voir la InputStream.available()
documentation:
il est particulièrement important de se rendre compte que vous ne devez pas utiliser ce méthode pour dimensionner un conteneur et de supposer que vous pouvez lire l'ensemble du flux sans avoir à redimensionner le conteneur. Ces appelants devrait probablement écrire tout ce qu'ils lisent à un ByteArrayOutputStream et convertir un tableau d'octets. Alternativement, si vous êtes en train de lire d'un fichier, fichier.length renvoie la longueur actuelle du fichier (bien que supposant la longueur du fichier ne peut pas changer peut être incorrect, lire un fichier est intrinsèquement laconique).
Java 7 et plus tard:
import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);
Java 8 way (merci à BufferedReader et Adam Bien )
private static byte[] readFully(InputStream input) throws IOException {
try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
return buffer.lines().collect(Collectors.joining("\n")).getBytes(<charset_can_be_specified>);
}
}
Note que cette solution essuie retour chariot ('\r') et peut être inappropriée.
l'autre cas pour obtenir le tableau correct des octets via stream, après avoir envoyé la requête au serveur et avoir attendu la réponse.
/**
* Begin setup TCP connection to PC app
* to open integrate connection between mobile app and pc app (or mobile app)
*/
mSocket = new Socket(IP, port);
// mSocket.setSoTimeout(30000);
DataOutputStream mDos = new DataOutputStream(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 = new DataInputStream(mSocket.getInputStream());
byte[] data = new byte[mDis.available()];
// Collecting data into byte array
for (int i = 0; i < data.length; i++)
data[i] = mDis.readByte();
// Converting collected data in byte array into String.
String RESPONSE = new String(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, L'entrée est en fait un FileInputStream, et vous pouvez appeler file.longueur() sur le fichier, ou le InputStream est un zipfile entrée InputStream, et vous pouvez les appeler zipEntry.length ()), alors il est beaucoup mieux d'écrire directement dans le tableau byte [] -- il utilise la moitié de la mémoire, et économise du temps.
// Read the file contents into a byte[] array
byte[] buf = new byte[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 operation
byte[] contents = bytesRead == inputStreamLength ? buf
: Arrays.copyOf(buf, bytesRead);
N.B. la dernière ligne ci-dessus traite des fichiers se tronquant pendant que le flux est lu, si vous devez gérer cette possibilité, mais si le fichier obtient plus pendant que le flux est lu, le contenu dans le tableau byte[] ne sera pas allongé pour inclure le nouveau contenu du fichier, le tableau sera simplement tronqué à l'ancienne longueur inputStreamLength .
j'utilise ceci.
public static byte[] toByteArray(InputStream is) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
byte[] b = new byte[4096];
int n = 0;
while ((n = is.read(b)) != -1) {
output.write(b, 0, n);
}
return output.toByteArray();
} finally {
output.close();
}
}
C'est ma version copier-coller:
@SuppressWarnings("empty-statement")
public static byte[] inputStreamToByte(InputStream is) throws IOException {
if (is == null) {
return null;
}
// Define a size if you have an idea of it.
ByteArrayOutputStream r = new ByteArrayOutputStream(2048);
byte[] read = new byte[512]; // Your buffer size.
for (int i; -1 != (i = is.read(read)); r.write(read, 0, i));
is.close();
return r.toByteArray();
}
envelopper dans un flux de données si cela est hors de la table pour une raison quelconque, il suffit d'utiliser la lecture pour marteler sur elle jusqu'à ce qu'il vous donne un -1 ou le bloc entier que vous avez demandé.
public int readFully(InputStream in, byte[] data) throws IOException {
int offset = 0;
int bytesRead;
boolean read = false;
while ((bytesRead = in.read(data, offset, data.length - offset)) != -1) {
read = true;
offset += bytesRead;
if (offset >= data.length) {
break;
}
}
return (read) ? offset : -1;
}
nous voyons un certain retard pour quelques transactions AWS, tout en convertissant l'objet S3 en ByteArray.
Remarque: S3 Objet d'un document PDF (taille max 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 intégrée 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);
dites-moi aussi si nous avons une autre meilleure façon de convertir l'objet s3 en bytearray
Voici une version optimisée, qui essaie d'éviter de copier des octets de données autant que possible:
private static byte[] loadStream (InputStream stream) throws IOException {
int available = stream.available();
int expectedSize = available > 0 ? available : -1;
return loadStream(stream, expectedSize);
}
private static byte[] loadStream (InputStream stream, int expectedSize) throws IOException {
int basicBufferSize = 0x4000;
int initialBufferSize = (expectedSize >= 0) ? expectedSize : basicBufferSize;
byte[] buf = new byte[initialBufferSize];
int pos = 0;
while (true) {
if (pos == buf.length) {
int readAhead = -1;
if (pos == expectedSize) {
readAhead = stream.read(); // test whether EOF is at expectedSize
if (readAhead == -1) {
return buf;
}
}
int newBufferSize = Math.max(2 * buf.length, basicBufferSize);
buf = Arrays.copyOf(buf, newBufferSize);
if (readAhead != -1) {
buf[pos++] = (byte)readAhead;
}
}
int len = stream.read(buf, pos, buf.length - pos);
if (len < 0) {
return Arrays.copyOf(buf, pos);
}
pos += len;
}
}
Sous Les Codes
public static byte[] serializeObj(Object obj) throws IOException {
ByteArrayOutputStream baOStream = new ByteArrayOutputStream();
ObjectOutputStream objOStream = new ObjectOutputStream(baOStream);
objOStream.writeObject(obj);
objOStream.flush();
objOStream.close();
return baOStream.toByteArray();
}
ou
BufferedImage img = ...
ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
ImageIO.write(img, "jpeg", baos);
baos.flush();
byte[] result = baos.toByteArray();
baos.close();
/*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 = new ByteArrayOutputStream();
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();
}
Ce qui fonctionne pour moi,
if(inputStream != null){
ByteArrayOutputStream contentStream = readSourceContent(inputStream);
String stringContent = contentStream.toString();
byte[] byteArr = encodeString(stringContent);
}
readSourceContent ()
public static ByteArrayOutputStream readSourceContent(InputStream inputStream) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
int nextChar;
try {
while ((nextChar = inputStream.read()) != -1) {
outputStream.write(nextChar);
}
outputStream.flush();
} catch (IOException e) {
throw new IOException("Exception occurred while reading content", e);
}
return outputStream;
}
encodeString ()
public static byte[] encodeString(String content) throws UnsupportedEncodingException {
byte[] bytes;
try {
bytes = content.getBytes();
} catch (UnsupportedEncodingException e) {
String msg = ENCODING + " is unsupported encoding type";
log.error(msg,e);
throw new UnsupportedEncodingException(msg, e);
}
return bytes;
}