Salah satu penggunaan yang dapat saya pikirkan adalah membaca objek serial dari file.
Mahm00d
2
Lain adalah menemukan tipe file menggunakan header.
James P.
Coba byte ini [] byte = null; BufferedInputStream fileInputStream = null; coba {File file = File baru (filePath); fileInputStream = BufferedInputStream baru (FileInputStream baru (file)); // fileInputStream = Thread.currentThread (). getContextClassLoader (). getResourceAsStream (this.filePath); byte = byte baru [(int) file.length ()]; fileInputStream.read (bytes); } catch (FileNotFoundException ex) {throw ex; }
Rohit Chaurasiya
Jawaban:
486
Itu tergantung pada apa arti terbaik untuk Anda. Produktivitas bijaksana, jangan menemukan kembali roda dan menggunakan Apache Commons. Yang ada di sini IOUtils.toByteArray(InputStream input).
@ymajoros: Benar sekali! Saya lebih suka memiliki beberapa baris kode tambahan daripada ketergantungan lainnya. Ketergantungan memiliki biaya tersembunyi. Anda harus tetap up to date dengan perpustakaan itu, sertakan ketergantungan dalam skrip build Anda dll, komunikasikan kepada orang-orang yang menggunakan kode Anda dll. Jika Anda sudah menggunakan perpustakaan yang memiliki kode untuk itu daripada menggunakannya, selain itu saya akan mengatakan tulis sendiri.
Stijn de Witt
11
Ini menjawab pertanyaan tentang bagaimana membaca file, tetapi bukan pertanyaan tentang bagaimana mengkonversi objek bertipe java.IO.File ke byte [].
Ingo
5
Bagaimana ini digunakan untuk membaca Fileke byte[]? Saya menggunakan Java6 jadi saya tidak bisa menggunakan metode NIO :(
PASTRY
4
@ymajoros, bisakah Anda berbagi "solusi 3-jalur standar" dengan kami, jadi kami tidak harus bergantung pada ketergantungan-menciptakan-roda-kembali?
matteo
3
@matteo: ada? Lihat jawaban lain, mis. Files.readAllBytes (). Sederhana, tidak ada ketergantungan.
Saya memiliki objek File, bukan path (dari permintaan posting http)
aldo.roman.nurena
81
@ aldo.roman.nurena JDK7 memperkenalkan metode File.toPath () yang akan memberi Anda Object Path.
KevinL
6
Anda bisa mendapatkan Path dari File. Coba: File file = File baru ("/ path"); Path path = Paths.get (file.getAbsolutePath ()); byte [] data = Files.readAllBytes (path);
gfelisberto
2
Bagaimana penutupan file ditangani dalam java.nio - dengan kata lain, haruskah kode di atas menutup sesuatu?
akauppi
4
@akauppi Lihat tautan dalam jawaban: "Metode ini memastikan bahwa file ditutup ..."
Ini sekarang merupakan pilihan yang lebih baik daripada jawaban yang diterima, yang membutuhkan Apache Commons.
james.garriss
1
Terima kasih :) Saya juga membutuhkan yang ini: String text = new String (Files.readAllBytes (File baru ("/ path / ke / file"). ToPath ())); yang aslinya dari stackoverflow.com/a/26888713/1257959
cgl
5
Di Android, dibutuhkan tingkat API min menjadi 26.
Ashutosh Chamoli
2
Anda harus menambahkan import java.nio.file.Files;dan import java.nio.file.Paths;jika Anda belum melakukannya.
Sam
164
import java.io.RandomAccessFile;RandomAccessFile f =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
Anda harus memeriksa nilai pengembalian f.read (). Di sini kadang-kadang bisa terjadi, bahwa Anda tidak akan membaca seluruh file.
bugs_
8
Situasi seperti itu dapat terjadi hanya jika file berubah saat Anda membacanya. Dalam semua kasus lainnya IOException dilemparkan. Untuk mengatasi masalah ini, saya sarankan untuk membuka file dalam mode baca-tulis: RandomAccessFile (fileName, "rw")
Dmitry Mitskevich
5
Saya dapat membayangkan sumber-sumber lain hanya membaca sebagian dari file (File ada di jaringan berbagi ...) readFully () memiliki kontrak yang Anda cari.
DT kupikir
3
Ingat bahwa RandomAccessFile tidak aman untuk thread. Jadi, sinkronisasi mungkin diperlukan dalam beberapa kasus.
bancer
@DmitryMitskevich Ada beberapa kasus lain, pada sistem file yang mungkin tidak sesuai. mis. membaca "file" di / proc / di linux dapat menyebabkan pembacaan singkat (yaitu Anda perlu perulangan untuk membaca semuanya)
nos
78
Pada dasarnya Anda harus membacanya di memori. Buka file, alokasikan array, dan baca konten dari file ke dalam array.
Cara paling sederhana adalah sesuatu yang mirip dengan ini:
Ini memiliki beberapa penyalinan konten file yang tidak perlu (sebenarnya data disalin tiga kali: dari file ke buffer, dari bufferke ByteArrayOutputStream, dari ByteArrayOutputStreamke array yang dihasilkan aktual).
Anda juga perlu memastikan Anda membaca dalam memori hanya file hingga ukuran tertentu (ini biasanya tergantung aplikasi) :-).
Anda juga perlu memperlakukan IOExceptionfungsi di luar.
Cara lain adalah ini:
publicbyte[] read(File file)throwsIOException,FileTooBigException{if(file.length()> MAX_FILE_SIZE){thrownewFileTooBigException(file);}byte[] buffer =newbyte[(int) file.length()];InputStream ios =null;try{
ios =newFileInputStream(file);if(ios.read(buffer)==-1){thrownewIOException("EOF reached while trying to read the whole file");}}finally{try{if(ios !=null)
ios.close();}catch(IOException e){}}return buffer;}
Ini tidak memiliki penyalinan yang tidak perlu.
FileTooBigExceptionadalah pengecualian aplikasi khusus. The MAX_FILE_SIZEkonstan adalah parameter aplikasi.
Untuk file besar, Anda mungkin harus berpikir algoritma pemrosesan aliran atau menggunakan pemetaan memori (lihat java.nio).
Pernyataan "ios.read (buffer)" dalam contoh kedua hanya akan membaca dalam 4096 byte pertama file (dengan asumsi buffer 4k yang sama seperti yang digunakan dalam contoh pertama). Agar contoh kedua berfungsi, saya pikir bacaan harus berada di dalam loop sementara yang memeriksa hasil untuk -1 (akhir file tercapai).
Stijn de Witt
Maaf, abaikan komentar saya di atas, melewatkan buffer pengaturan pernyataan hingga panjang file. Namun, saya lebih suka contoh pertama. Membaca seluruh file menjadi buffer dalam sekali jalan tidak dapat diskalakan. Anda akan berisiko kehabisan memori saat file berukuran besar.
Stijn de Witt
Cara "paling sederhana" akan memanfaatkan coba-dengan-sumber daya.
import org.apache.commons.io.FileUtils;publicclassProgram{publicstaticvoid main(String[] args)throwsIOException{File file =newFile(args[0]);// assume args[0] is the path to filebyte[] data =FileUtils.readFileToByteArray(file);...}}
Anda dapat menggunakan api NIO juga untuk melakukannya. Saya bisa melakukan ini dengan kode ini selama ukuran total file (dalam byte) akan cocok dengan int.
File f =newFile("c:\\wscp.script");FileInputStream fin =null;FileChannel ch =null;try{
fin =newFileInputStream(f);
ch = fin.getChannel();int size =(int) ch.size();MappedByteBuffer buf = ch.map(MapMode.READ_ONLY,0, size);byte[] bytes =newbyte[size];
buf.get(bytes);}catch(IOException e){// TODO Auto-generated catch block
e.printStackTrace();}finally{try{if(fin !=null){
fin.close();}if(ch !=null){
ch.close();}}catch(IOException e){
e.printStackTrace();}}
Saya pikir ini sangat cepat karena menggunakan MappedByteBuffer.
sama sekali tidak perlu menggunakan pemetaan memori jika Anda hanya akan membaca file sekali, dan akhirnya akan menggunakan memori dua kali lebih banyak daripada menggunakan FileInputStream normal.
james
1
Sayangnya MappedByteBuffer tidak secara otomatis dirilis.
Tom Hawtin - tackline
2
luar biasa, contoh baru termasuk printStackTrace, penanganan pengecualian rusak klasik.
james
Saya setuju .. Ini adalah hal-hal standar yang dilakukan oleh eclipse. Saya pikir saya harus memikirkan kembali pengecualian!
Amit
Saya telah melakukan benchmarking nio untuk membuat byte [] dari File. Selain menggunakan buffer langsung, memang dibutuhkan dua kali lebih banyak memori. Meskipun lebih cepat untuk file yang sangat besar (sekitar dua kali lebih cepat dari buffered IO untuk 200M) tampaknya kalah oleh faktor 5 untuk file sekitar 5M.
Chaffers
22
Jika Anda tidak memiliki Java 8, dan setuju dengan saya bahwa memasukkan pustaka besar untuk menghindari penulisan beberapa baris kode adalah ide yang buruk:
publicstaticbyte[] readBytes(InputStream inputStream)throwsIOException{byte[] b =newbyte[1024];ByteArrayOutputStream os =newByteArrayOutputStream();int c;while((c = inputStream.read(b))!=-1){
os.write(b,0, c);}return os.toByteArray();}
// Returns the contents of the file in a byte array.publicstaticbyte[] getBytesFromFile(File file)throwsIOException{// 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 largethrownewIOException("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;InputStream is =newFileInputStream(file);try{while(offset < bytes.length
&&(numRead=is.read(bytes, offset, bytes.length-offset))>=0){
offset += numRead;}}finally{
is.close();}// Ensure all the bytes have been read inif(offset < bytes.length){thrownewIOException("Could not completely read file "+file.getName());}return bytes;}
Juga, masukkan numRead di dalam loop. Deklarasikan variabel dalam cakupan valid terkecil yang Anda bisa. Menempatkannya di luar loop sementara hanya diperlukan untuk mengaktifkan tes "sementara" yang rumit itu; akan lebih baik untuk melakukan tes untuk EOF di dalam loop (dan melempar EOFException jika itu terjadi).
erickson
throw new IOException("File is too large!");apa yang harus kita lakukan ketika file terlalu besar? Apakah ada contoh tentang hal itu?
Fer
21
Cara sederhana untuk melakukannya:
File fff =newFile("/path/to/file");FileInputStream fileInputStream =newFileInputStream(fff);// int byteLength = fff.length(); // In android the result of file.length() is longlong byteLength = fff.length();// byte count of the file-contentbyte[] filecontent =newbyte[(int) byteLength];
fileInputStream.read(filecontent,0,(int) byteLength);
Bisakah Anda jelaskan di sini? Mengapa Anda berdebat?
Muhammad Sadiq
3
Tidak ada yang istimewa, tetapi Anda mengatakan yang paling sederhana dan saya melihat solusi yang lebih sederhana -> menurut saya itu bukan yang paling sederhana. Mungkin beberapa tahun yang lalu, tetapi dunia berubah. Saya tidak akan memberi label solusi saya sendiri dengan pernyataan seperti itu. ;) Kalau saja Anda menulis "Menurut saya yang paling sederhana adalah .." atau "yang paling sederhana yang saya temukan .." Tidak ingin mengganggu Anda, hanya berpikir baik untuk berkomunikasi ini.
BlondCode
@MuhammadSadiq: jangan impor apa pun .*, itu dianggap praktik buruk.
Sapphire_Brick
13
Guava memiliki Files.toByteArray () untuk menawarkan Anda. Ini memiliki beberapa keunggulan:
Ini mencakup kasus sudut di mana file melaporkan panjang 0 tetapi masih memiliki konten
Ini sangat dioptimalkan, Anda mendapatkan OutOfMemoryException jika mencoba membaca dalam file besar bahkan sebelum mencoba memuat file. (Melalui penggunaan file.length ()) yang cerdas
Menggunakan pendekatan yang sama dengan jawaban komunitas wiki, tetapi lebih bersih dan kompilasi di luar kotak (pendekatan yang lebih disukai jika Anda tidak ingin mengimpor Apache Commons libs, misalnya di Android):
publicstaticbyte[] getFileBytes(File file)throwsIOException{ByteArrayOutputStream ous =null;InputStream ios =null;try{byte[] buffer =newbyte[4096];
ous =newByteArrayOutputStream();
ios =newFileInputStream(file);int read =0;while((read = ios.read(buffer))!=-1)
ous.write(buffer,0, read);}finally{try{if(ous !=null)
ous.close();}catch(IOException e){// swallow, since not that important}try{if(ios !=null)
ios.close();}catch(IOException e){// swallow, since not that important}}return ous.toByteArray();}
sudah ada jawaban dengan saran ini dari Tom pada tahun 2009
Knut Herrmann
7
ReadFully Membaca b. Panjang byte dari file ini ke dalam array byte, mulai dari penunjuk file saat ini. Metode ini membaca berulang kali dari file hingga jumlah byte yang diminta dibaca. Metode ini memblokir hingga jumlah byte yang diminta dibaca, akhir aliran terdeteksi, atau pengecualian dilemparkan.
RandomAccessFile f =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
Jika Anda ingin membaca byte ke buffer byte yang dialokasikan sebelumnya, jawaban ini dapat membantu.
Tebakan pertama Anda mungkin akan digunakan InputStream read(byte[]). Namun, metode ini memiliki kelemahan yang membuatnya sulit digunakan: tidak ada jaminan bahwa array akan benar-benar diisi, bahkan jika tidak ada EOF yang ditemui.
Sebaliknya, lihatlah DataInputStream readFully(byte[]). Ini adalah pembungkus untuk aliran input, dan tidak memiliki masalah yang disebutkan di atas. Selain itu, metode ini melempar ketika EOF ditemui. Jauh lebih bagus.
Tidak hanya cara berikut mengonversi java.io.File ke byte [], saya juga menemukan itu menjadi cara tercepat untuk membaca dalam sebuah file, ketika menguji berbagai metode membaca file Java yang berbeda satu sama lain:
Izinkan saya menambahkan solusi lain tanpa menggunakan perpustakaan pihak ketiga. Ini menggunakan kembali pola penanganan pengecualian yang diusulkan oleh Scott ( tautan ). Dan saya memindahkan bagian yang jelek ke dalam pesan terpisah (saya akan bersembunyi di beberapa kelas FileUtils;))
publicvoid someMethod(){finalbyte[] buffer = read(newFile("test.txt"));}privatebyte[] read(finalFile file){if(file.isDirectory())thrownewRuntimeException("Unsupported operation, file "+ file.getAbsolutePath()+" is a directory");if(file.length()>Integer.MAX_VALUE)thrownewRuntimeException("Unsupported operation, file "+ file.getAbsolutePath()+" is too big");Throwable pending =null;FileInputStream in =null;finalbyte buffer[]=newbyte[(int) file.length()];try{
in =newFileInputStream(file);
in.read(buffer);}catch(Exception e){
pending =newRuntimeException("Exception occured on reading file "+ file.getAbsolutePath(), e);}finally{if(in !=null){try{
in.close();}catch(Exception e){if(pending ==null){
pending =newRuntimeException("Exception occured on closing file"+ file.getAbsolutePath(), e);}}}if(pending !=null){thrownewRuntimeException(pending);}}return buffer;}
jangan gunakan blok tangkapan berlubang. itu membuat debugging sulit.
Sapphire_Brick
1
//The file that you wanna convert into byte[]File file=newFile("/storage/0CE2-EA3D/DCIM/Camera/VID_20190822_205931.mp4");FileInputStream fileInputStream=newFileInputStream(file);byte[] data=newbyte[(int) file.length()];BufferedInputStream bufferedInputStream=newBufferedInputStream(fileInputStream);
bufferedInputStream.read(data,0,data.length);//Now the bytes of the file are contain in the "byte[] data"
Meskipun kode ini dapat memberikan solusi untuk pertanyaan, lebih baik menambahkan konteks mengapa / cara kerjanya. Ini dapat membantu pengguna di masa depan belajar, dan menerapkan pengetahuan itu ke kode mereka sendiri. Anda juga cenderung mendapat umpan balik positif dari pengguna dalam bentuk upvotes, ketika kode dijelaskan.
borchvm
Nah, itulah bagian penting yang akan saya ingat di posting selanjutnya. Terima kasih atas wawasan Anda yang bermanfaat.
Jawaban:
Itu tergantung pada apa arti terbaik untuk Anda. Produktivitas bijaksana, jangan menemukan kembali roda dan menggunakan Apache Commons. Yang ada di sini
IOUtils.toByteArray(InputStream input)
.sumber
File
kebyte[]
? Saya menggunakan Java6 jadi saya tidak bisa menggunakan metode NIO :(Dari JDK 7 Anda dapat menggunakan
Files.readAllBytes(Path)
.Contoh:
sumber
Sejak JDK 7 - satu liner:
Tidak diperlukan dependensi eksternal.
sumber
import java.nio.file.Files;
danimport java.nio.file.Paths;
jika Anda belum melakukannya.Dokumentasi untuk Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html
sumber
Pada dasarnya Anda harus membacanya di memori. Buka file, alokasikan array, dan baca konten dari file ke dalam array.
Cara paling sederhana adalah sesuatu yang mirip dengan ini:
Ini memiliki beberapa penyalinan konten file yang tidak perlu (sebenarnya data disalin tiga kali: dari file ke
buffer
, daribuffer
keByteArrayOutputStream
, dariByteArrayOutputStream
ke array yang dihasilkan aktual).Anda juga perlu memastikan Anda membaca dalam memori hanya file hingga ukuran tertentu (ini biasanya tergantung aplikasi) :-).
Anda juga perlu memperlakukan
IOException
fungsi di luar.Cara lain adalah ini:
Ini tidak memiliki penyalinan yang tidak perlu.
FileTooBigException
adalah pengecualian aplikasi khusus. TheMAX_FILE_SIZE
konstan adalah parameter aplikasi.Untuk file besar, Anda mungkin harus berpikir algoritma pemrosesan aliran atau menggunakan pemetaan memori (lihat
java.nio
).sumber
Seperti kata seseorang, Utilitas File Commons Apache mungkin memiliki apa yang Anda cari
Contoh penggunaan (
Program.java
):sumber
Anda dapat menggunakan api NIO juga untuk melakukannya. Saya bisa melakukan ini dengan kode ini selama ukuran total file (dalam byte) akan cocok dengan int.
Saya pikir ini sangat cepat karena menggunakan MappedByteBuffer.
sumber
Jika Anda tidak memiliki Java 8, dan setuju dengan saya bahwa memasukkan pustaka besar untuk menghindari penulisan beberapa baris kode adalah ide yang buruk:
Penelepon bertanggung jawab untuk menutup aliran.
sumber
sumber
throw new IOException("File is too large!");
apa yang harus kita lakukan ketika file terlalu besar? Apakah ada contoh tentang hal itu?Cara sederhana untuk melakukannya:
sumber
Cara termudah untuk membaca byte dari file
sumber
.*
, itu dianggap praktik buruk.Guava memiliki Files.toByteArray () untuk menawarkan Anda. Ini memiliki beberapa keunggulan:
sumber
sumber
Menggunakan pendekatan yang sama dengan jawaban komunitas wiki, tetapi lebih bersih dan kompilasi di luar kotak (pendekatan yang lebih disukai jika Anda tidak ingin mengimpor Apache Commons libs, misalnya di Android):
sumber
Saya percaya ini adalah cara termudah:
sumber
ReadFully Membaca b. Panjang byte dari file ini ke dalam array byte, mulai dari penunjuk file saat ini. Metode ini membaca berulang kali dari file hingga jumlah byte yang diminta dibaca. Metode ini memblokir hingga jumlah byte yang diminta dibaca, akhir aliran terdeteksi, atau pengecualian dilemparkan.
sumber
Jika Anda ingin membaca byte ke buffer byte yang dialokasikan sebelumnya, jawaban ini dapat membantu.
Tebakan pertama Anda mungkin akan digunakan
InputStream read(byte[])
. Namun, metode ini memiliki kelemahan yang membuatnya sulit digunakan: tidak ada jaminan bahwa array akan benar-benar diisi, bahkan jika tidak ada EOF yang ditemui.Sebaliknya, lihatlah
DataInputStream readFully(byte[])
. Ini adalah pembungkus untuk aliran input, dan tidak memiliki masalah yang disebutkan di atas. Selain itu, metode ini melempar ketika EOF ditemui. Jauh lebih bagus.sumber
Tidak hanya cara berikut mengonversi java.io.File ke byte [], saya juga menemukan itu menjadi cara tercepat untuk membaca dalam sebuah file, ketika menguji berbagai metode membaca file Java yang berbeda satu sama lain:
java.nio.file.Files.readAllBytes ()
sumber
Izinkan saya menambahkan solusi lain tanpa menggunakan perpustakaan pihak ketiga. Ini menggunakan kembali pola penanganan pengecualian yang diusulkan oleh Scott ( tautan ). Dan saya memindahkan bagian yang jelek ke dalam pesan terpisah (saya akan bersembunyi di beberapa kelas FileUtils;))
sumber
sumber
Cara lain untuk membaca byte dari file
sumber
sumber
Coba ini :
sumber
Di JDK8
sumber