Antworten:
Sie können Apache Commons IO verwenden , um diese und ähnliche Aufgaben zu erledigen.
Der IOUtils
Typ verfügt über eine statische Methode zum Lesen InputStream
und Zurückgeben von a byte[]
.
InputStream is;
byte[] bytes = IOUtils.toByteArray(is);
Intern erstellt dies ein ByteArrayOutputStream
und kopiert die Bytes in die Ausgabe und ruft dann auf toByteArray()
. Es verarbeitet große Dateien, indem die Bytes in Blöcken von 4 KB kopiert werden.
FastArrayList
oder deren weiche und schwache Referenzkarten an und kommen Sie zurück, um mir zu sagen, wie "gut getestet" diese Bibliothek ist. Es ist ein Müllhaufen
InputStream is;
byte[] filedata=ByteStreams.toByteArray(is);
Sie müssen jedes Byte von Ihrem lesen InputStream
und in ein schreiben ByteArrayOutputStream
.
Sie können das zugrunde liegende Byte-Array dann abrufen, indem Sie Folgendes aufrufen 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();
Schließlich gibt es nach zwanzig Jahren dank Java 9 eine einfache Lösung, ohne dass eine Bibliothek eines Drittanbieters erforderlich ist :
InputStream is;
…
byte[] array = is.readAllBytes();
Beachten Sie auch die praktischen Methoden readNBytes(byte[] b, int off, int len)
und die transferTo(OutputStream)
Berücksichtigung wiederkehrender Anforderungen.
Verwenden Sie Vanille-Java DataInputStream
und seine readFully
Methode (existiert seit mindestens Java 1.4):
...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...
Es gibt einige andere Varianten dieser Methode, aber ich verwende diese ständig für diesen Anwendungsfall.
DataInputStream
primär zum Lesen von Primärtypen (Longs, Shorts, Chars ...) aus einem Stream verwendet, sodass wir diese Verwendung als Missbrauch der Klasse ansehen können.
InputStream.read
.
Wenn Sie Google Guava verwenden , ist dies so einfach wie:
byte[] bytes = ByteStreams.toByteArray(inputStream);
ByteStreams
ist kommentiert mit@Beta
Wie immer hat auch Spring Framework (Spring-Core seit 3.2.2) etwas für Sie:StreamUtils.copyToByteArray()
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();
}
Sichere Lösung (mitclose
korrekterFähigkeit derStreams):
Java 9+ Version:
final byte[] bytes;
try (inputStream) {
bytes = inputStream.readAllBytes();
}
Java 8 Version:
public static byte[] readAllBytes(InputStream inputStream) throws IOException {
final int bufLen = 4 * 0x400; // 4KB
byte[] buf = new byte[bufLen];
int readLen;
IOException exception = null;
try {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
while ((readLen = inputStream.read(buf, 0, bufLen)) != -1)
outputStream.write(buf, 0, readLen);
return outputStream.toByteArray();
}
} catch (IOException e) {
exception = e;
throw e;
} finally {
if (exception == null) inputStream.close();
else try {
inputStream.close();
} catch (IOException e) {
exception.addSuppressed(e);
}
}
}
Kotlin- Version (wenn Java 9+ nicht verfügbar ist):
@Throws(IOException::class)
fun InputStream.readAllBytes(): ByteArray {
val bufLen = 4 * 0x400 // 4KB
val buf = ByteArray(bufLen)
var readLen: Int = 0
ByteArrayOutputStream().use { o ->
this.use { i ->
while (i.read(buf, 0, bufLen).also { readLen = it } != -1)
o.write(buf, 0, readLen)
}
return o.toByteArray()
}
}
Um verschachtelt zu vermeiden, use
siehe hier .
Benötigen Sie das Bild wirklich als byte[]
? Was genau erwarten Sie in derbyte[]
- dem vollständigen Inhalt einer Bilddatei, die in einem beliebigen Format der Bilddatei codiert ist, oder von RGB-Pixelwerten?
Andere Antworten hier zeigen Ihnen, wie Sie eine Datei in eine lesen byte[]
. Ihr byte[]
Testament enthält den genauen Inhalt der Datei, und Sie müssen diesen dekodieren, um etwas mit den Bilddaten zu tun.
Die Standard-API von Java zum Lesen (und Schreiben) von Bildern ist die ImageIO-API, die Sie im Paket finden javax.imageio
. Sie können ein Bild aus einer Datei mit nur einer Codezeile einlesen:
BufferedImage image = ImageIO.read(new File("image.jpg"));
Dies gibt Ihnen eine BufferedImage
, nicht eine byte[]
. Um bei den Bilddaten, können Sie rufen Sie getRaster()
auf der BufferedImage
. Dadurch erhalten Sie ein Raster
Objekt, das über Methoden für den Zugriff auf die Pixeldaten verfügt (es verfügt über mehrere getPixel()
/getPixels()
Methoden).
Nachschlagen der API - Dokumentation javax.imageio.ImageIO
, java.awt.image.BufferedImage
, java.awt.image.Raster
usw.
ImageIO unterstützt standardmäßig eine Reihe von Bildformaten: JPEG, PNG, BMP, WBMP und GIF. Es ist möglich, Unterstützung für weitere Formate hinzuzufügen (Sie benötigen ein Plug-In, das die ImageIO-Dienstanbieterschnittstelle implementiert).
Siehe auch das folgende Tutorial: Arbeiten mit Bildern
Für den Fall, dass noch jemand nach einer Lösung ohne Abhängigkeit sucht und wenn Sie eine Datei haben .
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);
Wenn Sie die Apache commons-io-Bibliothek nicht verwenden möchten, stammt dieses Snippet aus der Klasse sun.misc.IOUtils. Es ist fast doppelt so schnell wie die übliche Implementierung mit 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;
}
@ Adamski: Sie können Puffer vollständig vermeiden.
Code, der von http://www.exampledepot.com/egs/java.io/File2ByteArray.html kopiert wurde (Ja, er ist sehr ausführlich, benötigt jedoch die halbe Speichergröße wie die andere Lösung.)
// 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;
}
is.close()
ob offset < bytes.length
oder InputStream
wird nicht geschlossen, wenn diese Ausnahme ausgelöst wird.
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();
InputStream
in einem BufferedInputStream
vor diesem Code würde die OS-Anrufe reduzieren und die Leistung Nachteile deutlich zu mildern, wird dieser Code noch von einem Puffer zum anderen unnötigen manuellen Kopier Arbeit tun.
Java 9 gibt Ihnen endlich eine schöne Methode:
InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
InputStram.readAllBytes()
jenem Einzeiler?
Ich weiß, dass es zu spät ist, aber hier denke ich, ist eine sauberere Lösung, die besser lesbar ist ...
/**
* 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();
}
Java 8 Way (danke an BufferedReader und 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>);
}
}
Beachten Sie, dass diese Lösung den Wagenrücklauf ('\ r') löscht und unangemessen sein kann.
String
. OP bittet um byte[]
.
\r
ein Problem sein. Diese Methode konvertiert die Bytes in Zeichen und wieder zurück (unter Verwendung des Standardzeichensatzes für InputStreamReader). Alle Bytes, die in der Standardzeichencodierung nicht gültig sind (z. B. -1 für UTF-8 unter Linux), werden beschädigt, wodurch möglicherweise sogar die Anzahl der Bytes geändert wird.
Ich habe versucht, die Antwort von @ numan mit einem Fix zum Schreiben von Mülldaten zu bearbeiten, aber die Bearbeitung wurde abgelehnt. Obwohl dieser kurze Code nichts Brillantes ist, kann ich keine bessere Antwort finden. Folgendes macht für mich am meisten Sinn:
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();
Übrigens muss ByteArrayOutputStream nicht geschlossen werden. try / finally-Konstrukte wurden aus Gründen der Lesbarkeit weggelassen
Siehe die InputStream.available()
Dokumentation:
Es ist besonders wichtig zu wissen, dass Sie diese Methode nicht verwenden dürfen, um die Größe eines Containers zu bestimmen, und davon auszugehen, dass Sie den gesamten Stream lesen können, ohne die Größe des Containers ändern zu müssen. Solche Aufrufer sollten wahrscheinlich alles, was sie lesen, in einen ByteArrayOutputStream schreiben und diesen in ein Byte-Array konvertieren. Wenn Sie alternativ aus einer Datei lesen, gibt File.length die aktuelle Länge der Datei zurück (obwohl die Annahme, dass sich die Länge der Datei nicht ändern kann, möglicherweise falsch ist, ist das Lesen einer Datei von Natur aus rassig).
Wickeln Sie es in einen DataInputStream ein, wenn dies aus irgendeinem Grund vom Tisch ist. Verwenden Sie einfach read, um darauf zu hämmern, bis Sie -1 oder den gesamten Block erhalten, nach dem Sie gefragt haben.
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;
}
Bei einigen AWS-Transaktionen tritt eine gewisse Verzögerung auf, während das S3-Objekt in ByteArray konvertiert wird.
Hinweis: S3-Objekt ist ein PDF-Dokument (maximale Größe 3 MB).
Wir verwenden die Option 1 (org.apache.commons.io.IOUtils), um das S3-Objekt in ByteArray zu konvertieren. Wir haben festgestellt, dass S3 die eingebaute IOUtils-Methode zum Konvertieren des S3-Objekts in ByteArray bereitstellt. Wir bitten Sie, zu bestätigen, wie das S3-Objekt am besten in ByteArray konvertiert werden kann, um die Verzögerung zu vermeiden.
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);
Lassen Sie mich auch wissen, ob wir eine andere bessere Möglichkeit haben, das s3-Objekt in Bytearray zu konvertieren
Der andere Fall, um das richtige Byte-Array über den Stream zu erhalten, nachdem die Anforderung an den Server gesendet und auf die Antwort gewartet wurde.
/**
* 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);
Sie erstellen eine zusätzliche Kopie, wenn Sie ByteArrayOutputStream verwenden. Wenn Sie die Länge des Streams kennen, bevor Sie mit dem Lesen beginnen (z. B. ist der InputStream tatsächlich ein FileInputStream, und Sie können file.length () für die Datei aufrufen, oder der InputStream ist ein Zipfile-Eintrag InputStream, und Sie können zipEntry aufrufen. length ()), dann ist es weitaus besser, direkt in das byte [] -Array zu schreiben - es verbraucht die Hälfte des Speichers und spart Zeit.
// 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);
Hinweis: Die letzte Zeile oben befasst sich mit Dateien, die während des Lesens des Streams abgeschnitten werden. Wenn Sie diese Möglichkeit nutzen müssen, aber wenn die Datei während des Lesens des Streams länger wird, wird der Inhalt im Array byte [] nicht verlängert Um den neuen Dateiinhalt einzuschließen , wird das Array einfach auf die alte Länge inputStreamLength gekürzt .
Ich benutze das.
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();
}
}
Dies ist meine Copy-Paste-Version:
@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();
}
Java 7 und höher:
import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);
sun.misc.IOUtils
ist nicht "Java 7". Es handelt sich um eine proprietäre, implementierungsspezifische Klasse, die in anderen JRE-Implementierungen möglicherweise nicht vorhanden ist und in einer der nächsten Versionen ohne Vorwarnung verschwinden kann.
Hier ist eine optimierte Version, die versucht, das Kopieren von Datenbytes so weit wie möglich zu vermeiden:
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;
}
}
Lösung in Kotlin (funktioniert natürlich auch in Java), die beide Fälle umfasst, in denen Sie die Größe kennen oder nicht:
fun InputStream.readBytesWithSize(size: Long): ByteArray? {
return when {
size < 0L -> this.readBytes()
size == 0L -> ByteArray(0)
size > Int.MAX_VALUE -> null
else -> {
val sizeInt = size.toInt()
val result = ByteArray(sizeInt)
readBytesIntoByteArray(result, sizeInt)
result
}
}
}
fun InputStream.readBytesIntoByteArray(byteArray: ByteArray,bytesToRead:Int=byteArray.size) {
var offset = 0
while (true) {
val read = this.read(byteArray, offset, bytesToRead - offset)
if (read == -1)
break
offset += read
if (offset >= bytesToRead)
break
}
}
Wenn Sie die Größe kennen, sparen Sie doppelt so viel Speicher wie bei den anderen Lösungen (in einem kurzen Moment, aber dennoch nützlich). Das liegt daran, dass Sie den gesamten Stream bis zum Ende lesen und dann in ein Byte-Array konvertieren müssen (ähnlich wie ArrayList, das Sie nur in ein Array konvertieren).
Wenn Sie beispielsweise mit Android arbeiten und etwas Uri zu handhaben haben, können Sie versuchen, die Größe folgendermaßen zu ermitteln:
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/878126
FileUtilEx.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 = 0L
while (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 = 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();
}