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).
@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.
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 =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
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.
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:
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;}
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).
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.
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);...}}
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:
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();}
Dzwoniący jest odpowiedzialny za zamknięcie strumienia.
// 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;}
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 =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);
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ę.
Obejmuje przypadek narożny, w którym pliki zgłaszają długość 0, ale nadal zawierają treść
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 ())
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):
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();}
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 =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
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.
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 :
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;))
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;}
nie używaj pustych bloków zaczepowych. utrudnia debugowanie.
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"
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.
Odpowiedzi:
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)
.źródło
File
nabyte[]
? Używam Java6, więc nie mogę używać metod NIO :(Z JDK 7 możesz korzystać
Files.readAllBytes(Path)
.Przykład:
źródło
Od JDK 7 - jedna wkładka:
Nie są wymagane żadne zewnętrzne zależności.
źródło
import java.nio.file.Files;
aimport java.nio.file.Paths;
jeśli jeszcze tego nie zrobiłeś.Dokumentacja dla Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html
źródło
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:
Powoduje to niepotrzebne kopiowanie zawartości pliku (dane są kopiowane trzy razy: z pliku do
buffer
, odbuffer
doByteArrayOutputStream
, zByteArrayOutputStream
do 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ć
IOException
zewnętrzną funkcję.Innym sposobem jest to:
Nie wymaga to niepotrzebnego kopiowania.
FileTooBigException
to wyjątek niestandardowej aplikacji.MAX_FILE_SIZE
Stał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
).źródło
Jak ktoś powiedział, Apache Commons File Utils może mieć to, czego szukasz
Przykład użycia (
Program.java
):źródło
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.
Myślę, że jest bardzo szybki, odkąd używa MappedByteBuffer.
źródło
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:
Dzwoniący jest odpowiedzialny za zamknięcie strumienia.
źródło
źródło
throw new IOException("File is too large!");
co powinniśmy zrobić, gdy plik jest zbyt duży? Czy jest na to jakiś przykład?Prosty sposób to zrobić:
źródło
Najprostszy sposób na odczyt bajtów z pliku
źródło
.*
, jest to uważane za złą praktykę.Guava ma do zaoferowania Files.toByteArray () . Ma kilka zalet:
źródło
źródło
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):
źródło
Wierzę, że jest to najłatwiejszy sposób:
źródło
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.
źródło
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.źródło
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 ()
źródło
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;))
źródło
źródło
Kolejny sposób na odczyt bajtów z pliku
źródło
źródło
Spróbuj tego :
źródło
W JDK8
źródło