File ke byte [] di Jawa


757

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


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


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

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.


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


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


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

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.


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.


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

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

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

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.

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

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

8

Saya percaya ini adalah cara termudah:

org.apache.commons.io.FileUtils.readFileToByteArray(file);

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

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.


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

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

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

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

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"

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

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

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.