Plik do bajtu [] w Javie


757

Jak przekonwertować java.io.Filena a byte[]?


Jednym z zastosowań, które mogę wymyślić, jest odczytywanie szeregowanych obiektów z pliku.
Mahm00d

2
Innym jest znalezienie typu pliku za pomocą nagłówka.
James P.

Spróbuj Ten bajt [] bajty = null; BufferedInputStream fileInputStream = null; spróbuj {Plik plik = nowy plik (filePath); fileInputStream = nowy BufferedInputStream (nowy FileInputStream (plik)); // fileInputStream = Thread.currentThread (). getContextClassLoader (). getResourceAsStream (this.filePath); bajty = nowy bajt [(int) file.length ()]; fileInputStream.read (bytes); } catch (FileNotFoundException ex) {throw ex; }
Rohit Chaurasiya

Odpowiedzi:


486

To zależy od tego, co najlepiej dla Ciebie znaczy. Jeśli chodzi o produktywność, nie wymyślaj na nowo koła i korzystaj z Apache Commons. Co jest tutaj IOUtils.toByteArray(InputStream input).


29
@ymajoros: Tak prawda! Wolę mieć dodatkowe wiersze kodu niż kolejną zależność. Zależności mają ukryte koszty. Musisz być na bieżąco z tą biblioteką, uwzględniać zależność w skryptach kompilacji itp., Przekazywać ją osobom używającym twojego kodu itp. Jeśli już korzystasz z biblioteki, która ma dla niej kod, użyj tego, inaczej powiedziałbym napisz to sam.
Stijn de Witt

11
Odpowiada to na pytanie, jak odczytać plik, ale nie na pytanie, jak przekonwertować obiekt typu java.IO.File na bajt [].
Ingo

5
Jak to kiedyś przeczytać Filena byte[]? Używam Java6, więc nie mogę używać metod NIO :(
PASTRY

4
@ymajoros, czy uprzejmie podzieliłbyś się z nami jakimś „standardowym rozwiązaniem 3-liniowym”, więc nie musimy polegać na nowej zależności?
matteo

3
@matteo: any? Zobacz inne odpowiedzi, np. Files.readAllBytes (). Prosta, bez zależności.
ymajoros

1292

Z JDK 7 możesz korzystać Files.readAllBytes(Path).

Przykład:

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

File file;
// ...(file is initialised)...
byte[] fileContent = Files.readAllBytes(file.toPath());

10
Mam obiekt File, a nie ścieżkę (z żądania HTTP post)
aldo.roman.nurena 28.10.2013

81
@ aldo.roman.nurena JDK7 wprowadził metodę File.toPath (), która da ci obiekt ścieżki.
KevinL

6
Możesz uzyskać ścieżkę z pliku. Spróbuj: Plik plik = nowy plik („/ ścieżka”); Ścieżka ścieżka = Paths.get (file.getAbsolutePath ()); byte [] data = Files.readAllBytes (ścieżka);
gfelisberto,

2
Jak obsługiwane jest zamykanie plików w java.nio - innymi słowy, czy powyższy kod powinien coś zamknąć?
akauppi,

4
@akauppi Zobacz link w odpowiedzi: „Metoda gwarantuje, że plik zostanie zamknięty ...”
Bernhard Barker

226

Od JDK 7 - jedna wkładka:

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

Nie są wymagane żadne zewnętrzne zależności.


13
To jest teraz lepszy wybór niż zaakceptowana odpowiedź, która wymaga Apache Commons.
james.garriss

1
Dzięki :) Potrzebowałem również tego: String text = new String (Files.readAllBytes (new File ("/ path / to / file"). ToPath ())); który pochodzi z stackoverflow.com/a/26888713/1257959
cgl

5
W Androidzie wymagany minimalny poziom API to 26.
Ashutosh Chamoli

2
Musisz dodać, import java.nio.file.Files;a import java.nio.file.Paths;jeśli jeszcze tego nie zrobiłeś.
Sam

164
import java.io.RandomAccessFile;
RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

Dokumentacja dla Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html


2
Musisz sprawdzić wartość zwracaną przez f.read (). Czasami może się zdarzyć, że nie przeczytasz całego pliku.
błędy_

8
Taka sytuacja może wystąpić tylko wtedy, gdy plik się zmienia podczas czytania. We wszystkich innych przypadkach zgłaszany jest wyjątek IOException. Aby rozwiązać ten problem, sugeruję, aby otworzyć plik w trybie do odczytu i zapisu: RandomAccessFile (fileName, „rw”)
Dmitry Mitskevich

5
Mogę sobie wyobrazić, że inne źródła tylko do odczytu części pliku (plik jest w udziale sieciowym ...) readFully () ma kontrakt, którego szukasz.
D Myślał

3
Pamiętaj, że RandomAccessFile nie jest bezpieczny dla wątków. Dlatego w niektórych przypadkach może być potrzebna synchronizacja.
bancer

@DmitryMitskevich Istnieją również inne przypadki dotyczące systemów plików, które są prawdopodobnie niezgodne. np. czytanie „plików” w / proc / on linux może powodować krótkie odczyty (tzn. potrzebujesz pętli, aby przeczytać wszystko)
nr

78

Zasadniczo musisz przeczytać to w pamięci. Otwórz plik, przydziel tablicę i wczytaj zawartość pliku do tablicy.

Najprostszym sposobem jest coś podobnego do tego:

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

Powoduje to niepotrzebne kopiowanie zawartości pliku (dane są kopiowane trzy razy: z pliku do buffer, od bufferdo ByteArrayOutputStream, z ByteArrayOutputStreamdo rzeczywistej tablicy wynikowej).

Musisz także upewnić się, że czytasz w pamięci tylko pliki do określonego rozmiaru (zwykle zależy to od aplikacji) :-).

Musisz także traktować IOExceptionzewnętrzną funkcję.

Innym sposobem jest to:

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

Nie wymaga to niepotrzebnego kopiowania.

FileTooBigExceptionto wyjątek niestandardowej aplikacji. MAX_FILE_SIZEStała to parametrów roboczych.

W przypadku dużych plików prawdopodobnie powinieneś pomyśleć o algorytmie przetwarzania strumienia lub użyć mapowania pamięci (patrz java.nio).


ios należy zadeklarować poza próbą
Daryl Spitzer,

Instrukcja „ios.read (bufor)” w drugim przykładzie będzie czytana tylko w pierwszych 4096 bajtach pliku (przy założeniu tego samego bufora 4k, jaki zastosowano w pierwszym przykładzie). Aby drugi przykład zadziałał, myślę, że odczyt musi znajdować się w pętli while, która sprawdza wynik dla -1 (osiągnięty koniec pliku).
Stijn de Witt

Niestety, odrzuć moją uwagę powyżej, przegapiłem bufor ustawień instrukcji do długości pliku. Mimo wszystko podoba mi się ten pierwszy przykład. Odczytywanie całego pliku do bufora za jednym razem nie jest skalowalne. Gdy plik będzie duży, zaryzykujesz opróżnienie pamięci.
Stijn de Witt

„Najprostszym” sposobem byłoby użycie try-with-resources.
Sina Madani

Fajnie, ale trochę gadatliwie.
Sapphire_Brick

77

Jak ktoś powiedział, Apache Commons File Utils może mieć to, czego szukasz

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

Przykład użycia ( 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

Aby to zrobić, możesz również użyć interfejsu NIO. Mógłbym to zrobić z tym kodem, o ile całkowity rozmiar pliku (w bajtach) zmieściłby się w 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();
    }
}

Myślę, że jest bardzo szybki, odkąd używa MappedByteBuffer.


2
absolutnie nie ma potrzeby używania mapowania pamięci, jeśli zamierzasz odczytać plik tylko raz, a skończy się to użyciem dwukrotnie więcej pamięci niż przy użyciu zwykłego FileInputStream.
James

1
Niestety MappedByteBuffer nie jest automatycznie zwalniany.
Tom Hawtin - hals

2
niesamowite, nowy przykład zawiera printStackTrace, klasyczną obsługę wyjątków zepsutych.
James

Zgadzam się. To jest domyślna rzecz, którą wprowadza zaćmienie. Myślę, że powinienem powtórzyć wyjątek!
Amit

Testowałem nio w celu stworzenia bajtu [] z pliku. Poza użyciem bezpośredniego bufora zajmuje dwa razy więcej pamięci. Chociaż jest to szybsze w przypadku bardzo dużych plików (około dwa razy szybsze niż buforowane IO dla 200M), wydaje się, że traci około 5 razy w przypadku plików około 5M.
Chaffers

22

Jeśli nie masz Java 8 i zgadzasz się ze mną, że dołączenie ogromnej biblioteki, aby uniknąć napisania kilku wierszy kodu, jest złym pomysłem:

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

Dzwoniący jest odpowiedzialny za zamknięcie strumienia.


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

Ponadto umieść numRead w pętli. Deklaruj zmienne w najmniejszym możliwym zakresie. Umieszczenie go poza pętlą while jest konieczne tylko w celu umożliwienia tego skomplikowanego testu „podczas”; lepiej byłoby wykonać test EOF wewnątrz pętli (i zgłosić wyjątek EOFEx, jeśli wystąpi).
erickson

throw new IOException("File is too large!");co powinniśmy zrobić, gdy plik jest zbyt duży? Czy jest na to jakiś przykład?
Fer

21

Prosty sposób to zrobić:

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

Istnieją prostsze sposoby, takie jak wspomniane już linijki.
Sapphire_Brick

@Sapphire_Brick Prostsze sposoby tak - ale te same wkładki nie pasują do wszystkich sytuacji. Takich jak Android.
Behr

17

Najprostszy sposób na odczyt bajtów z pliku

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
Argumentuję, że jestem „najprostszym sposobem” :)
BlondCode

Czy możesz to wyjaśnić tutaj? Dlaczego się kłócisz?
Muhammad Sadiq

3
Nic specjalnego, ale mówisz najprostsze i widzę prostsze rozwiązania -> moim zdaniem nie jest najprostsze. Może to było kilka lat temu, ale świat się zmienia. Oświadczeniem takim nie oznaczałbym własnych rozwiązań. ;) Gdybyś tylko napisał: „Moim zdaniem najprostsze jest…” lub „najprostsze, jakie znalazłem ..” Nie chcę ci przeszkadzać, po prostu miło mi to przekazać.
BlondCode

@MuhammadSadiq: nie importuj niczego .*, jest to uważane za złą praktykę.
Sapphire_Brick

13

Guava ma do zaoferowania Files.toByteArray () . Ma kilka zalet:

  1. Obejmuje przypadek narożny, w którym pliki zgłaszają długość 0, ale nadal zawierają treść
  2. Jest wysoce zoptymalizowany, otrzymujesz wyjątek OutOfMemoryException, jeśli próbujesz odczytać duży plik, zanim nawet spróbujesz go załadować. (Poprzez sprytne użycie file.length ())
  3. Nie musisz wymyślać koła od nowa.

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

Jaki to poziom JDK?
Jonathan S. Fisher

11

Stosując to samo podejście, co odpowiedź wiki społeczności, ale czystsze i kompilując po wyjęciu z pudełka (preferowane podejście, jeśli nie chcesz importować bibliotek Apache Commons, np. Na Androida):

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

Wierzę, że jest to najłatwiejszy sposób:

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

7
już jest odpowiedź na tę sugestię od Toma w 2009 r.
Knut Herrmann

7

ReadFully Odczytuje bajty długości b. Z tego pliku do tablicy bajtów, zaczynając od bieżącego wskaźnika pliku. Ta metoda odczytuje wielokrotnie z pliku, aż zostanie odczytana żądana liczba bajtów. Ta metoda blokuje, dopóki żądana liczba bajtów nie zostanie odczytana, nie zostanie wykryty koniec strumienia lub zgłoszony zostanie wyjątek.

RandomAccessFile f = new RandomAccessFile(fileName, "r");
byte[] b = new byte[(int)f.length()];
f.readFully(b);

5

Jeśli chcesz wczytać bajty do wstępnie przydzielonego bufora bajtów, ta odpowiedź może pomóc.

Twoje pierwsze przypuszczenie byłoby prawdopodobnie użyć InputStream read(byte[]). Jednak ta metoda ma wadę, która sprawia, że ​​korzystanie z niej jest nadmiernie trudne: nie ma gwarancji, że tablica zostanie całkowicie wypełniona, nawet jeśli nie napotkamy EOF.

Zamiast tego spójrz na DataInputStream readFully(byte[]). Jest to opakowanie dla strumieni wejściowych i nie ma wyżej wspomnianego problemu. Dodatkowo metoda ta rzuca się, gdy napotkamy EOF. Dużo ładniejszy.


4

Następujący sposób nie tylko konwertuje plik java.io.File na bajt [], ale także okazało się, że jest to najszybszy sposób na odczyt pliku, podczas testowania wielu różnych metod odczytu plików Java :

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

Pozwól mi dodać inne rozwiązanie bez korzystania z bibliotek stron trzecich. Ponownie wykorzystuje wzorzec obsługi wyjątków zaproponowany przez Scotta ( link ). I przeniosłem brzydką część do osobnej wiadomości (ukryłbym się w klasie 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

Kolejny sposób na odczyt bajtów z pliku

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

nie używaj pustych bloków zaczepowych. utrudnia debugowanie.
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
Chociaż ten kod może stanowić rozwiązanie tego pytania, lepiej dodać kontekst wyjaśniający, dlaczego / jak to działa. Może to pomóc przyszłym użytkownikom w nauce i zastosowaniu tej wiedzy do własnego kodu. Prawdopodobnie będziesz otrzymywać pozytywne opinie od użytkowników w postaci pozytywnych opinii, gdy kod zostanie wyjaśniony.
borchvm

Cóż, to ważna część, o której będę pamiętać w przyszłych postach. Dziękujemy za przydatne informacje.
Usama Mehmood

0

Spróbuj tego :

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

Wymaga to konkretnej implementacji środowiska JRE, która zepsuje aplikację, jeśli zostanie uruchomiona na innym środowisku JRE.
rattaman

2
mały błąd: czy IOException i nie IOexception, ale dzięki :)
Matan Marciano

1
@MatanMarciano: my bad
Sapphire_Brick

-7

W JDK8

Stream<String> lines = Files.lines(path);
String data = lines.collect(Collectors.joining("\n"));
lines.close();

2
Przeczytaj pytanie, mój przyjaciel mówiący po francusku, pyta o konwersję na „bajt []”, a twoja odpowiedź tego nie zawiera.
Kaiser Keister

2
Nie zapewnia to nawet zdalnej opcji odpowiedzi na konwersję do bajtu []!
Anddo
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.