Secara internal ini membuat ByteArrayOutputStreamdan menyalin byte ke output, lalu memanggil toByteArray(). Ini menangani file besar dengan menyalin byte dalam blok 4KiB.
Untuk yang ingin menulis 4 baris kode, Anda berpikir bahwa mengimpor dependensi pihak ketiga bermanfaat?
oxbow_lakes
217
Jika ada perpustakaan yang menangani persyaratan, dan berkaitan dengan pemrosesan untuk file besar, dan sudah teruji dengan baik, tentu pertanyaannya adalah mengapa saya menulisnya sendiri? Toples hanya 107KB dan jika Anda memerlukan satu metode dari itu, Anda kemungkinan akan menggunakan yang lain juga
Penjual Kaya
242
@oxbow_lakes: mengingat jumlah implementasi salah yang mengejutkan dari fitur ini yang pernah saya lihat dalam kehidupan pengembang saya, saya merasa ya itu sangat layak untuk ketergantungan eksternal untuk memperbaikinya.
Joachim Sauer
17
Mengapa tidak pergi dan melihat-lihat hal-hal seperti Apache commons FastArrayListatau Peta referensi lunak & lemah mereka dan kembali untuk memberi tahu saya seberapa "teruji" perpustakaan ini. Ini tumpukan sampah
oxbow_lakes
87
Selain Apache commons-io, periksa kelas ByteStreams dari Google Guava . InputStream is;byte[] filedata=ByteStreams.toByteArray(is);
michaelok
446
Anda perlu membaca setiap byte dari Anda InputStreamdan menulisnya ke a ByteArrayOutputStream.
Anda kemudian dapat mengambil array byte yang mendasarinya dengan memanggil 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();
Bagaimana dengan ukuran byte yang baru dibuat []. Mengapa 16384? Bagaimana saya bisa menentukan ukuran tepat yang tepat? Terima kasih banyak.
Ondrej Bozek
6
16384 adalah pilihan yang cukup sewenang-wenang meskipun saya cenderung mendukung kekuatan 2 untuk meningkatkan peluang array menyelaraskan dengan batas kata. Jawaban pihentagy menunjukkan bagaimana Anda dapat menghindari penggunaan buffer perantara, tetapi mengalokasikan array dengan ukuran yang benar. Kecuali jika Anda berurusan dengan file besar, saya pribadi lebih suka kode di atas, yang lebih elegan dan dapat digunakan untuk InputStreams di mana jumlah byte untuk dibaca tidak diketahui sebelumnya.
Adamski
@ Adamski Bukankah menciptakan array byte jauh lebih besar daripada yang Anda harapkan akan ada di stream, membuang-buang memori?
Paul Brewczynski
@ Benlu: Ya itu benar. Namun, dalam contoh saya array byte hanya 16Kb dan sangat kecil menurut standar saat ini. Juga, tentu saja memori ini akan dibebaskan lagi sesudahnya.
Adamski
5
@Adamski Banyak infrastruktur perangkat keras, server web, dan komponen lapisan OS menggunakan buffer 4K untuk memindahkan data, jadi itulah alasan untuk angka pastinya, tetapi poin utamanya adalah Anda mendapatkan sedikit peningkatan kinerja dengan melampaui 4K bahwa itu umumnya dianggap boros memori. Saya berasumsi ini masih benar, karena ini adalah pengetahuan lama yang saya miliki!
312
Akhirnya, setelah dua puluh tahun, ada solusi sederhana tanpa perlu perpustakaan pihak ke-3, berkat Java 9 :
+1 untuk menggunakan perpustakaan standar alih-alih ketergantungan pihak ke-3. Sayangnya itu tidak berfungsi untuk saya karena saya tidak tahu panjang aliran di muka.
Andrew Spencer
2
apa itu imgFile? Itu tidak bisa menjadi InputStream, yang seharusnya menjadi input dari metode ini
Janus Troelsen
4
@janus itu adalah "File". cara ini hanya berfungsi jika Anda mengetahui panjang file atau jumlah byte yang harus dibaca.
dermoritz
5
Hal yang menarik, tetapi Anda harus tahu panjang yang tepat dari (bagian dari) aliran untuk membaca. Selain itu, kelas DataInputStreamadalah primer yang digunakan untuk membaca tipe primer (Longs, Shorts, Chars ...) dari aliran, sehingga kita dapat melihat penggunaan ini sebagai penyalahgunaan kelas.
Olivier Faucheux
17
Jika Anda sudah tahu panjang data untuk dibaca dari arus, ini tidak lebih baik dari itu InputStream.read.
Logan Pickup
119
Jika Anda menggunakan google jambu , ini akan sesederhana:
Seperti kebanyakan orang lain, saya ingin menghindari menggunakan perpustakaan pihak ke-3 untuk sesuatu yang sangat sederhana, tetapi Java 9 bukan pilihan saat ini ... untungnya, saya sudah menggunakan 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();}
Ini adalah contoh dan dengan demikian, singkatnya adalah urutan hari. Juga mengembalikan nol di sini akan menjadi pilihan yang tepat dalam beberapa kasus (meskipun dalam lingkungan produksi Anda juga akan memiliki penanganan dan dokumentasi pengecualian yang tepat).
11
Saya memahami singkatnya dalam sebuah contoh, tetapi mengapa tidak hanya membuat metode contoh melempar IOException daripada menelannya dan mengembalikan nilai yang tidak berarti?
pendor
4
Saya telah mengambil kebebasan untuk berubah dari 'return null' ke 'throw IOException'
kritzikratzi
3
Try-with-resources tidak diperlukan di sini, karena ByteArrayOutputStream # close () tidak melakukan apa-apa. (ByteArrayOutputStream # flush () tidak diperlukan dan tidak melakukan apa-apa juga.)
Luke Hutchison
25
Solusi aman (dengan kemampuanclosestream dengan benar):
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=0ByteArrayOutputStream().use { o ->this.use { i ->while(i.read(buf,0, bufLen).also { readLen = it }!=-1)
o.write(buf,0, readLen)}return o.toByteArray()}}
Bukankah itu berarti bahwa pada titik tertentu Anda akan menggunakan memori yang berlipat ganda, karena Anda memiliki buffer dan array byte? Apakah tidak ada cara untuk mengirim byte secara langsung ke array byte keluaran?
pengembang android
@androiddeveloper; Maafkan saya. Saya tidak tahu jawabannya! Tapi saya rasa tidak. Saya pikir cara ini (menggunakan buffer) adalah cara yang dioptimalkan.
Mir-Ismaili
Saya sudah memeriksanya, tetapi sepertinya itu satu-satunya solusi yang dapat Anda pilih ketika Anda tidak tahu ukurannya. Jika Anda sudah tahu ukurannya, Anda bisa langsung membuat byte-array dengan ukuran yang diberikan dan mengisinya. Jadi, Anda menggunakan fungsi yang akan mendapatkan parameter ukuran byte, dan jika valid, gunakan untuk langsung membuat dan mengisi array byte, tanpa membuat objek besar lainnya.
pengembang android
@androiddeveloper; Terima kasih atas informasi anda. Saya tidak kenal mereka.
Mir-Ismaili
19
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:
Ini akan memberi Anda BufferedImage, bukan a byte[]. Untuk mendapatkan data gambar, Anda dapat menghubungi getRaster()di BufferedImage. Ini akan memberi Anda Rasterobjek, 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.Rasterdll
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).
Katakanlah, bagaimana jika array byte terlalu besar yang dapat menyebabkan OOM untuk heap? Apakah ada solusi serupa yang akan menggunakan JNI untuk menyimpan byte, dan nantinya kita akan dapat menggunakan inputStream dari data yang disimpan di sana (semacam cache sementara)?
pengembang android
14
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:
Ini sedikit solusi aneh, panjang adalah batas atas pada panjang array. Jika Anda tahu panjangnya, yang Anda butuhkan adalah: byte [] output = byte baru [panjang]; is.read (output); (tapi lihat jawaban saya)
Luke Hutchison
@ luke-hutchison seperti yang saya katakan, ini adalah solusi dari sun.misc.IOUtils. Dalam kasus yang paling umum Anda tidak tahu ukuran dimuka InputStream, jadi jika (length == -1) length = Integer.MAX_VALUE; berlaku. Solusi ini berfungsi, bahkan jika panjang yang diberikan lebih besar dari panjang InputStream.
Kristian Kraljic
@LukeHutchison Jika Anda tahu panjangnya, Anda bisa mengatasinya dengan beberapa baris. Jika Anda melihat setiap jawaban, semua orang mengeluh bahwa panjangnya tidak diketahui. Akhirnya jawaban yang standar, dapat digunakan dengan Java 7 Android, dan tidak memerlukan perpustakaan eksternal.
Csaba Toth
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;}
Tentu saja, tetapi mereka harus tahu ukurannya: "Saya ingin membaca gambar"
pihentagy
1
jika Anda tahu ukurannya, maka java menyediakan kode untuk Anda. lihat jawaban saya atau google untuk "DataInputStream" dan metode readFully.
dermoritz
Anda harus menambahkan is.close()jika offset < bytes.lengthatau InputStreamtidak akan ditutup jika pengecualian itu dilemparkan.
Jared Rummler
3
Maka lebih baik, Anda harus menggunakan coba-dengan-sumber daya
pihentagy
8
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();
Namun, biasanya OS sudah buffer cukup untuk ini tidak menjadi masalah besar untuk file yang lebih kecil. Ini tidak seperti kepala hard disk akan membaca setiap byte secara terpisah (hard disk adalah pelat kaca pembalik dengan informasi kode magnetik di atasnya, agak seperti ikon aneh yang kita gunakan untuk menyimpan data: P).
Maarten Bodewes
6
@ Maarten Bodewes: sebagian besar perangkat memiliki semacam transfer blok, jadi tidak setiap read () akan menyebabkan akses perangkat yang sebenarnya, memang, tetapi memiliki panggilan OS per byte sudah cukup untuk mematikan kinerja. Sementara membungkus InputStreamdalam BufferedInputStreamsebelum 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.
Holger
4
Java 9 akhirnya akan memberi Anda metode yang bagus:
Apa perbedaan antara ini dan InputStram.readAllBytes()itu satu garis ?
Slava Semushin
2
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.
*/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();}
Bukan hanya \ritu 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.
seanf
Sepertinya ini jawaban yang bagus, tapi berorientasi teks. Hati-hati pembeli.
Wheezil
1
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 =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 tidak perlu ditutup. coba / akhirnya konstruk dihilangkan agar mudah dibaca
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.
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 =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);
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[] 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 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 .
Tambahkan beberapa penjelasan dengan jawaban untuk bagaimana jawaban ini membantu OP dalam memperbaiki masalah saat ini
ρяσѕρєя K
0
Ini adalah versi salin-tempel saya:
@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();}
Sementara potongan kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan sangat membantu untuk meningkatkan kualitas posting Anda. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, dan orang-orang itu mungkin tidak tahu alasan untuk saran kode Anda.
Ferrybig
0
Java 7 dan yang lebih baru:
import sun.misc.IOUtils;...InputStream in =...;byte[] buf =IOUtils.readFully(in,-1,false);
sun.misc.IOUtilsbukan "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.
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 ->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}}
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/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();}
Menutup dan memerah bos adalah buang-buang klik keyboard. Menutup aliran input lebih mungkin membantu. Membaca satu byte pada suatu waktu tidak efisien. Lihat jawaban numan.
Jawaban:
Anda dapat menggunakan Apache Commons IO untuk menangani ini dan tugas serupa.
The
IOUtils
jenis memiliki metode statis untuk membacaInputStream
dan mengembalikanbyte[]
.Secara internal ini membuat
ByteArrayOutputStream
dan menyalin byte ke output, lalu memanggiltoByteArray()
. Ini menangani file besar dengan menyalin byte dalam blok 4KiB.sumber
FastArrayList
atau Peta referensi lunak & lemah mereka dan kembali untuk memberi tahu saya seberapa "teruji" perpustakaan ini. Ini tumpukan sampahInputStream is;
byte[] filedata=ByteStreams.toByteArray(is);
Anda perlu membaca setiap byte dari Anda
InputStream
dan menulisnya ke aByteArrayOutputStream
.Anda kemudian dapat mengambil array byte yang mendasarinya dengan memanggil
toByteArray()
:sumber
Akhirnya, setelah dua puluh tahun, ada solusi sederhana tanpa perlu perpustakaan pihak ke-3, berkat Java 9 :
Perhatikan juga metode kenyamanan
readNBytes(byte[] b, int off, int len)
dantransferTo(OutputStream)
mengatasi kebutuhan yang berulang.sumber
Gunakan vanilla Java's
DataInputStream
danreadFully
Metodenya (setidaknya ada sejak Java 1.4):Ada beberapa rasa lain dari metode ini, tetapi saya menggunakan ini sepanjang waktu untuk use case ini.
sumber
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:
sumber
ByteStreams
dijelaskan dengan@Beta
Seperti biasa, juga kerangka Pegas (pegas-inti sejak 3.2.2) memiliki sesuatu untuk Anda:
StreamUtils.copyToByteArray()
sumber
sumber
Solusi aman (dengan kemampuan
close
stream dengan benar):Versi Java 9+:
Versi Java 8:
Versi Kotlin (ketika Java 9+ tidak dapat diakses):
Untuk menghindari bersarang
use
lihat di sini .sumber
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[]
. Andabyte[]
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:Ini akan memberi Anda
BufferedImage
, bukan abyte[]
. Untuk mendapatkan data gambar, Anda dapat menghubungigetRaster()
diBufferedImage
. Ini akan memberi AndaRaster
objek, yang memiliki metode untuk mengakses data pixel (memiliki beberapagetPixel()
/getPixels()
metode).Lookup dokumentasi API untuk
javax.imageio.ImageIO
,java.awt.image.BufferedImage
,java.awt.image.Raster
dllImageIO 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
sumber
Dalam kasus seseorang masih mencari solusi tanpa ketergantungan dan Jika Anda memiliki file .
sumber
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:
sumber
sumber
@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.)
sumber
is.close()
jikaoffset < bytes.length
atauInputStream
tidak akan ditutup jika pengecualian itu dilemparkan.sumber
InputStream
dalamBufferedInputStream
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:
sumber
InputStram.readAllBytes()
itu satu garis ?Saya tahu sudah terlambat tetapi di sini saya pikir ini adalah solusi bersih yang lebih mudah dibaca ...
sumber
Java 8 way (terima kasih kepada BufferedReader dan Adam Bien )
Perhatikan bahwa solusi ini menghapus carriage return ('\ r') dan dapat menjadi tidak tepat.
sumber
String
. OP memintabyte[]
.\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:
btw ByteArrayOutputStream tidak perlu ditutup. coba / akhirnya konstruk dihilangkan agar mudah dibaca
sumber
Lihat
InputStream.available()
dokumentasi:sumber
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.
sumber
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:
Pilihan 2:
Juga beri tahu saya jika kami memiliki cara lain yang lebih baik untuk mengonversi objek s3 menjadi bytearray
sumber
Kasus lain untuk mendapatkan byte array yang benar melalui aliran, setelah mengirim permintaan ke server dan menunggu respons.
sumber
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.
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 .
sumber
Saya menggunakan ini.
sumber
Ini adalah versi salin-tempel saya:
sumber
Java 7 dan yang lebih baru:
sumber
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.Anda dapat mencoba Cactoos :
sumber
Ini adalah versi yang dioptimalkan, yang berusaha menghindari menyalin byte data sebanyak mungkin:
sumber
Solusi di Kotlin (tentu saja akan bekerja di Jawa), yang mencakup kedua kasus ketika Anda mengetahui ukurannya atau tidak:
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:
sumber
sumber