File ke byte [] di Jawa

757

Bagaimana saya mengonversi a java.io.Fileke a byte[]?

Ben Noland
sumber
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).

svachon
sumber
29
@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.
ymajoros
1293

Dari JDK 7 Anda dapat menggunakan Files.readAllBytes(Path).

Contoh:

import java.io.File;
import java.nio.file.Files;

File file;
// ...(file is initialised)...
byte[] fileContent = Files.readAllBytes(file.toPath());
Michael Pollmeier
sumber
10
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 ..."
Bernhard Barker
226

Sejak JDK 7 - satu liner:

byte[] array = Files.readAllBytes(Paths.get("/path/to/file"));

Tidak diperlukan dependensi eksternal.

Paulius Matulionis
sumber
13
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 = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

Dokumentasi untuk Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html

Dmitry Mitskevich
sumber
2
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:

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(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) {
        }

        try {
            if (ios != null)
                ios.close();
        } catch (IOException e) {
        }
    }
    return ous.toByteArray();
}

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:

public byte[] read(File file) throws IOException, FileTooBigException {
    if (file.length() > MAX_FILE_SIZE) {
        throw new FileTooBigException(file);
    }

    byte[] buffer = new byte[(int) file.length()];
    InputStream ios = null;
    try {
        ios = new FileInputStream(file);
        if (ios.read(buffer) == -1) {
            throw new IOException(
                    "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).

Mihai Toader
sumber
ios perlu dinyatakan di luar coba
Daryl Spitzer
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.
Sina Madani
Keren, tapi sedikit untuk diucapkan.
Sapphire_Brick
77

Seperti kata seseorang, Utilitas File Commons Apache mungkin memiliki apa yang Anda cari

public static byte[] readFileToByteArray(File file) throws IOException

Contoh penggunaan ( Program.java):

import org.apache.commons.io.FileUtils;
public class Program {
    public static void main(String[] args) throws IOException {
        File file = new File(args[0]);  // assume args[0] is the path to file
        byte[] data = FileUtils.readFileToByteArray(file);
        ...
    }
}
Tom
sumber
23

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 = new File("c:\\wscp.script");
FileInputStream fin = null;
FileChannel ch = null;
try {
    fin = new FileInputStream(f);
    ch = fin.getChannel();
    int size = (int) ch.size();
    MappedByteBuffer buf = ch.map(MapMode.READ_ONLY, 0, size);
    byte[] bytes = new byte[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.

Amit
sumber
2
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:

public static byte[] readBytes(InputStream inputStream) throws IOException {
    byte[] b = new byte[1024];
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    int c;
    while ((c = inputStream.read(b)) != -1) {
        os.write(b, 0, c);
    }
    return os.toByteArray();
}

Penelepon bertanggung jawab untuk menutup aliran.

Jeffrey Blattman
sumber
21
// Returns the contents of the file in a byte array.
    public static byte[] getBytesFromFile(File file) throws IOException {        
        // 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
            throw new IOException("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;

        InputStream is = new FileInputStream(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 in
        if (offset < bytes.length) {
            throw new IOException("Could not completely read file "+file.getName());
        }
        return bytes;
    }
Cuga
sumber
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 = new File("/path/to/file");
FileInputStream fileInputStream = new FileInputStream(fff);

// int byteLength = fff.length(); 

// In android the result of file.length() is long
long byteLength = fff.length(); // byte count of the file-content

byte[] filecontent = new byte[(int) byteLength];
fileInputStream.read(filecontent, 0, (int) byteLength);
Sudip Bhandari
sumber
Ada cara yang lebih sederhana, seperti one-liners yang telah disebutkan.
Sapphire_Brick
@ Safhire_Brick Cara-cara yang lebih sederhana ya - tetapi kalimat yang satu ini tidak cocok untuk semua situasi. Seperti Android.
Behr
17

Cara termudah untuk membaca byte dari file

import java.io.*;

class ReadBytesFromFile {
    public static void main(String args[]) throws Exception {
        // getBytes from anyWhere
        // I'm getting byte array from File
        File file = null;
        FileInputStream fileStream = new FileInputStream(file = new File("ByteArrayInputStreamClass.java"));

        // Instantiate array
        byte[] arr = new byte[(int) file.length()];

        // read All bytes of File stream
        fileStream.read(arr, 0, arr.length);

        for (int X : arr) {
            System.out.print((char) X);
        }
    }
}
Muhammad Sadiq
sumber
1
Saya berdebat menjadi "Jalan
Paling
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:

  1. Ini mencakup kasus sudut di mana file melaporkan panjang 0 tetapi masih memiliki konten
  2. Ini sangat dioptimalkan, Anda mendapatkan OutOfMemoryException jika mencoba membaca dalam file besar bahkan sebelum mencoba memuat file. (Melalui penggunaan file.length ()) yang cerdas
  3. Anda tidak perlu menemukan kembali roda.
jontejj
sumber
12
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;

File file = getYourFile();
Path path = file.toPath();
byte[] data = Files.readAllBytes(path);
BlondCode
sumber
Apa level JDK ini?
Jonathan S. Fisher
11

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):

public static byte[] getFileBytes(File file) throws IOException {
    ByteArrayOutputStream ous = null;
    InputStream ios = null;
    try {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        ios = new FileInputStream(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();
}
manmal
sumber
8

Saya percaya ini adalah cara termudah:

org.apache.commons.io.FileUtils.readFileToByteArray(file);
Cristian Tetic
sumber
7
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 = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);
Tarun M
sumber
5

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.

Laurens Holst
sumber
4

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 ()

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

public class ReadFile_Files_ReadAllBytes {
  public static void main(String [] pArgs) throws IOException {
    String fileName = "c:\\temp\\sample-10KB.txt";
    File file = new File(fileName);

    byte [] fileBytes = Files.readAllBytes(file.toPath());
    char singleChar;
    for(byte b : fileBytes) {
      singleChar = (char) b;
      System.out.print(singleChar);
    }
  }
}
gomisha
sumber
3

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;))

public void someMethod() {
    final byte[] buffer = read(new File("test.txt"));
}

private byte[] read(final File file) {
    if (file.isDirectory())
        throw new RuntimeException("Unsupported operation, file "
                + file.getAbsolutePath() + " is a directory");
    if (file.length() > Integer.MAX_VALUE)
        throw new RuntimeException("Unsupported operation, file "
                + file.getAbsolutePath() + " is too big");

    Throwable pending = null;
    FileInputStream in = null;
    final byte buffer[] = new byte[(int) file.length()];
    try {
        in = new FileInputStream(file);
        in.read(buffer);
    } catch (Exception e) {
        pending = new RuntimeException("Exception occured on reading file "
                + file.getAbsolutePath(), e);
    } finally {
        if (in != null) {
            try {
                in.close();
            } catch (Exception e) {
                if (pending == null) {
                    pending = new RuntimeException(
                        "Exception occured on closing file" 
                             + file.getAbsolutePath(), e);
                }
            }
        }
        if (pending != null) {
            throw new RuntimeException(pending);
        }
    }
    return buffer;
}
Andreas Dolk
sumber
3
public static byte[] readBytes(InputStream inputStream) throws IOException {
    byte[] buffer = new byte[32 * 1024];
    int bufferSize = 0;
    for (;;) {
        int read = inputStream.read(buffer, bufferSize, buffer.length - bufferSize);
        if (read == -1) {
            return Arrays.copyOf(buffer, bufferSize);
        }
        bufferSize += read;
        if (bufferSize == buffer.length) {
            buffer = Arrays.copyOf(buffer, bufferSize * 2);
        }
    }
}
mazatwork
sumber
1

Cara lain untuk membaca byte dari file

Reader reader = null;
    try {
        reader = new FileReader(file);
        char buf[] = new char[8192];
        int len;
        StringBuilder s = new StringBuilder();
        while ((len = reader.read(buf)) >= 0) {
            s.append(buf, 0, len);
            byte[] byteArray = s.toString().getBytes();
        }
    } catch(FileNotFoundException ex) {
    } catch(IOException e) {
    }
    finally {
        if (reader != null) {
            reader.close();
        }
    }
Muhammad Aamir Ali
sumber
jangan gunakan blok tangkapan berlubang. itu membuat debugging sulit.
Sapphire_Brick
1
//The file that you wanna convert into byte[]
File file=new File("/storage/0CE2-EA3D/DCIM/Camera/VID_20190822_205931.mp4"); 

FileInputStream fileInputStream=new FileInputStream(file);
byte[] data=new byte[(int) file.length()];
BufferedInputStream bufferedInputStream=new BufferedInputStream(fileInputStream);
bufferedInputStream.read(data,0,data.length);

//Now the bytes of the file are contain in the "byte[] data"
Usama Mehmood
sumber
1
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.
Usama Mehmood
0

Coba ini :

import sun.misc.IOUtils;
import java.io.IOException;

try {
    String path="";
    InputStream inputStream=new FileInputStream(path);
    byte[] data=IOUtils.readFully(inputStream,-1,false);
}
catch (IOException e) {
    System.out.println(e);
}
Maifee Ul Asad
sumber
Itu membutuhkan implementasi JRE tertentu yang akan merusak aplikasi jika dijalankan pada JRE lain.
rattaman
2
sedikit kesalahan: adalah IOException dan bukan IOexception, tapi terima kasih :)
Matan Marciano
1
@MatanMarciano: my bad
Sapphire_Brick
-7

Di JDK8

Stream<String> lines = Files.lines(path);
String data = lines.collect(Collectors.joining("\n"));
lines.close();
beaucequebec
sumber
2
Baca pertanyaan teman berbahasa Perancis saya, pertanyaannya tentang konversi ke "byte []" dan jawaban Anda tidak memberikannya.
Kaiser Keister
2
Ini tidak menyediakan opsi jarak jauh untuk menjawab untuk konversi ke byte []!
Anddo