Jawaban:
Anda dapat menggunakan Apache Commons IO untuk menangani ini dan tugas serupa.
The IOUtils
jenis memiliki metode statis untuk membaca InputStream
dan mengembalikan byte[]
.
InputStream is;
byte[] bytes = IOUtils.toByteArray(is);
Secara internal ini membuat ByteArrayOutputStream
dan menyalin byte ke output, lalu memanggil toByteArray()
. Ini menangani file besar dengan menyalin byte dalam blok 4KiB.
FastArrayList
atau Peta referensi lunak & lemah mereka dan kembali untuk memberi tahu saya seberapa "teruji" perpustakaan ini. Ini tumpukan sampah
InputStream is;
byte[] filedata=ByteStreams.toByteArray(is);
Anda perlu membaca setiap byte dari Anda InputStream
dan menulisnya ke a ByteArrayOutputStream
.
Anda kemudian dapat mengambil array byte yang mendasarinya dengan memanggil 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();
Akhirnya, setelah dua puluh tahun, ada solusi sederhana tanpa perlu perpustakaan pihak ke-3, berkat Java 9 :
InputStream is;
…
byte[] array = is.readAllBytes();
Perhatikan juga metode kenyamanan readNBytes(byte[] b, int off, int len)
dan transferTo(OutputStream)
mengatasi kebutuhan yang berulang.
Gunakan vanilla Java's DataInputStream
dan readFully
Metodenya (setidaknya ada sejak Java 1.4):
...
byte[] bytes = new byte[(int) file.length()];
DataInputStream dis = new DataInputStream(new FileInputStream(file));
dis.readFully(bytes);
...
Ada beberapa rasa lain dari metode ini, tetapi saya menggunakan ini sepanjang waktu untuk use case ini.
DataInputStream
adalah primer yang digunakan untuk membaca tipe primer (Longs, Shorts, Chars ...) dari aliran, sehingga kita dapat melihat penggunaan ini sebagai penyalahgunaan kelas.
InputStream.read
.
Jika Anda menggunakan google jambu , ini akan sesederhana:
byte[] bytes = ByteStreams.toByteArray(inputStream);
ByteStreams
dijelaskan dengan@Beta
Seperti biasa, juga kerangka Pegas (pegas-inti sejak 3.2.2) memiliki sesuatu untuk Anda: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();
}
Solusi aman (dengan kemampuanclose
stream dengan benar):
Versi Java 9+:
final byte[] bytes;
try (inputStream) {
bytes = inputStream.readAllBytes();
}
Versi Java 8:
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);
}
}
}
Versi Kotlin (ketika Java 9+ tidak dapat diakses):
@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()
}
}
Untuk menghindari bersarang use
lihat di sini .
Apakah Anda benar-benar membutuhkan gambar sebagai byte[]
? Apa tepatnya yang Anda harapkan di Internet?byte[]
- konten lengkap file gambar, yang dikodekan dalam format apa pun file gambar, atau nilai-nilai piksel RGB?
Jawaban lain di sini menunjukkan kepada Anda cara membaca file ke dalam byte[]
. Anda byte[]
akan berisi konten file yang tepat, dan Anda harus men-decode itu untuk melakukan apa saja dengan data gambar.
API standar Java untuk membaca (dan menulis) gambar adalah API ImageIO, yang dapat Anda temukan dalam paket javax.imageio
. Anda dapat membaca dalam gambar dari file hanya dengan satu baris kode:
BufferedImage image = ImageIO.read(new File("image.jpg"));
Ini akan memberi Anda BufferedImage
, bukan a byte[]
. Untuk mendapatkan data gambar, Anda dapat menghubungi getRaster()
di BufferedImage
. Ini akan memberi Anda Raster
objek, yang memiliki metode untuk mengakses data pixel (memiliki beberapa getPixel()
/getPixels()
metode).
Lookup dokumentasi API untuk javax.imageio.ImageIO
, java.awt.image.BufferedImage
, java.awt.image.Raster
dll
ImageIO mendukung sejumlah format gambar secara default: JPEG, PNG, BMP, WBMP dan GIF. Dimungkinkan untuk menambahkan dukungan untuk lebih banyak format (Anda memerlukan plug-in yang mengimplementasikan antarmuka penyedia layanan ImageIO).
Lihat juga tutorial berikut: Bekerja dengan Gambar
Dalam kasus seseorang masih mencari solusi tanpa ketergantungan dan Jika Anda memiliki file .
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);
Jika Anda tidak ingin menggunakan pustaka Apache commons-io, cuplikan ini diambil dari kelas sun.misc.IOUtils. Ini hampir dua kali lebih cepat dari implementasi umum menggunakan 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: Anda dapat menghindari buffer sepenuhnya.
Kode disalin dari http://www.exampledepot.com/egs/java.io/File2ByteArray.html (Ya, sangat verbose, tetapi membutuhkan setengah ukuran memori sebagai solusi lain.)
// 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()
jika offset < bytes.length
atau InputStream
tidak akan ditutup jika pengecualian itu dilemparkan.
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
dalam BufferedInputStream
sebelum kode yang akan mengurangi OS-panggilan dan mengurangi kelemahan kinerja secara signifikan, kode yang masih akan melakukan yang tidak perlu kerja menyalin pengguna dari satu buffer yang lain.
Java 9 akhirnya akan memberi Anda metode yang bagus:
InputStream in = ...;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
in.transferTo( bos );
byte[] bytes = bos.toByteArray();
InputStram.readAllBytes()
itu satu garis ?
Saya tahu sudah terlambat tetapi di sini saya pikir ini adalah solusi bersih yang lebih mudah dibaca ...
/**
* 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 (terima kasih kepada BufferedReader dan 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>);
}
}
Perhatikan bahwa solusi ini menghapus carriage return ('\ r') dan dapat menjadi tidak tepat.
String
. OP meminta byte[]
.
\r
itu yang bisa menjadi masalah. Metode ini mengubah byte ke karakter dan kembali lagi (menggunakan karakter default yang ditetapkan untuk InputStreamReader). Setiap byte yang tidak valid dalam pengkodean karakter default (katakanlah, -1 untuk UTF-8 di Linux) akan rusak, bahkan berpotensi mengubah jumlah byte.
Saya mencoba mengedit jawaban @ numan dengan perbaikan untuk menulis data sampah tetapi edit ditolak. Sementara potongan pendek kode ini tidak brilian, saya tidak bisa melihat jawaban lain yang lebih baik. Inilah yang paling masuk akal bagi saya:
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 tidak perlu ditutup. coba / akhirnya konstruk dihilangkan agar mudah dibaca
Lihat InputStream.available()
dokumentasi:
Sangat penting untuk menyadari bahwa Anda tidak boleh menggunakan metode ini untuk mengukur ukuran wadah dan menganggap bahwa Anda dapat membaca keseluruhan aliran tanpa perlu mengubah ukuran wadah. Penelepon semacam itu mungkin harus menulis semua yang mereka baca ke ByteArrayOutputStream dan mengonversinya menjadi array byte. Atau, jika Anda membaca dari file, File.length mengembalikan panjang file saat ini (meskipun dengan asumsi panjang file tidak dapat berubah mungkin salah, membaca file secara inheren bersemangat).
Bungkus dalam DataInputStream jika itu ada di luar meja untuk beberapa alasan, cukup gunakan baca untuk palu di atasnya sampai memberi Anda -1 atau seluruh blok yang Anda minta.
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;
}
Kami melihat beberapa keterlambatan untuk beberapa transaksi AWS, saat mengonversi objek S3 ke ByteArray.
Catatan: Objek S3 adalah dokumen PDF (ukuran maksimal adalah 3 mb).
Kami menggunakan opsi # 1 (org.apache.commons.io.IOUtils) untuk mengonversi objek S3 ke ByteArray. Kami telah memperhatikan S3 menyediakan metode IOUtils inbuild untuk mengubah objek S3 menjadi ByteArray, kami meminta Anda untuk mengonfirmasi apa cara terbaik untuk mengonversi objek S3 ke ByteArray untuk menghindari keterlambatan.
Pilihan 1:
import org.apache.commons.io.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Pilihan 2:
import com.amazonaws.util.IOUtils;
is = s3object.getObjectContent();
content =IOUtils.toByteArray(is);
Juga beri tahu saya jika kami memiliki cara lain yang lebih baik untuk mengonversi objek s3 menjadi bytearray
Kasus lain untuk mendapatkan byte array yang benar melalui aliran, setelah mengirim permintaan ke server dan menunggu respons.
/**
* 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);
Anda sedang melakukan salinan tambahan jika Anda menggunakan ByteArrayOutputStream. Jika Anda mengetahui panjang aliran sebelum Anda mulai membacanya (mis. InputStream sebenarnya adalah FileInputStream, dan Anda dapat memanggil file.length () pada file, atau InputStream adalah entri zipfile, InputStream, dan Anda dapat memanggil zipEntry. length ()), maka jauh lebih baik untuk menulis langsung ke array byte [] - ia menggunakan setengah memori, dan menghemat waktu.
// 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);
NB baris terakhir di atas berkaitan dengan file yang terpotong saat stream sedang dibaca, jika Anda perlu menangani kemungkinan itu, tetapi jika file menjadi lebih lama saat stream sedang dibaca, konten dalam array byte [] tidak akan diperpanjang untuk memasukkan konten file baru, array hanya akan dipotong ke inputStreamLength panjang lama .
Saya menggunakan ini.
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();
}
}
Ini adalah versi salin-tempel saya:
@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 dan yang lebih baru:
import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);
sun.misc.IOUtils
bukan "Java 7". Ini adalah kelas khusus, implementasi khusus yang mungkin tidak ada dalam implementasi JRE lain dan dapat menghilang tanpa peringatan di salah satu rilis berikutnya.
Ini adalah versi yang dioptimalkan, yang berusaha menghindari menyalin byte data sebanyak mungkin:
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;
}
}
Solusi di Kotlin (tentu saja akan bekerja di Jawa), yang mencakup kedua kasus ketika Anda mengetahui ukurannya atau tidak:
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
}
}
Jika Anda tahu ukurannya, itu menghemat Anda memiliki dua kali lipat memori yang digunakan dibandingkan dengan solusi lain (dalam waktu singkat, tetapi masih bisa bermanfaat). Itu karena Anda harus membaca seluruh aliran hingga akhir, dan kemudian mengonversinya menjadi array byte (mirip dengan ArrayList yang Anda konversi menjadi hanya array).
Jadi, jika Anda menggunakan Android, misalnya, dan Anda dapat menangani beberapa Uri, Anda dapat mencoba untuk mendapatkan ukuran menggunakan ini:
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();
}