Depende do que melhor significa para você. Em termos de produtividade, não reinvente a roda e use o Apache Commons. Qual é aqui IOUtils.toByteArray(InputStream input).
@ymajoros: Tão verdade! Prefiro ter algumas linhas extras de código do que outra dependência. Dependências têm custos ocultos. Você precisa manter-se atualizado com essa biblioteca, incluir a dependência nos scripts de construção, etc., comunicá-la às pessoas que usam seu código, etc. escreva você mesmo.
Stijn de Witt
11
Isso responde à questão de como ler um arquivo, mas não à questão de como converter um objeto do tipo java.IO.File em byte [].
Ingo
5
Como isso é usado para ler um Filepara byte[]? Estou usando Java6 então não posso usar os métodos NIO :(
PASTELARIA
4
@ymajoros, você poderia compartilhar conosco qualquer "solução padrão de 3 linhas", para que não tenhamos que confiar em uma dependência de reinventar a roda?
Matteo
3
@matteo: algum? Veja outras respostas, por exemplo, Files.readAllBytes (). Simples, sem dependência.
Eu tenho um objeto File, não um caminho (da solicitação de postagem http)
aldo.roman.nurena 28/10
81
@ aldo.roman.nurena O JDK7 introduziu um método File.toPath () que fornecerá um Path Object.
KevinL
6
Você pode obter um caminho de um arquivo. Tente: Arquivo file = new File ("/ path"); Caminho path = Paths.get (file.getAbsolutePath ()); byte [] data = Files.readAllBytes (caminho);
Gfelisberto
2
Como o fechamento do arquivo é tratado no java.nio - em outras palavras, o código acima deve fechar alguma coisa?
akauppi
4
@akauppi Veja o link na resposta: "O método garante que o arquivo seja fechado ..."
Agora é uma escolha melhor do que a resposta aceita, que requer o Apache Commons.
James.garriss 15/09/2015
1
Obrigado :) Eu também precisava deste: String text = new String (Files.readAllBytes (new File ("/ path / to / file"). ToPath ())); que é originalmente de stackoverflow.com/a/26888713/1257959
cgl
5
Em Android, que exige nível API min para ser 26.
Ashutosh Chamoli
2
Você precisará adicionar import java.nio.file.Files;e import java.nio.file.Paths;se ainda não o tiver.
Sam
164
import java.io.RandomAccessFile;RandomAccessFile f =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
Você deve verificar o valor de retorno de f.read (). Às vezes, aqui pode acontecer que você não leia o arquivo inteiro.
bugs_
8
Essa situação pode ocorrer apenas se o arquivo estiver sendo alterado enquanto você o estiver lendo. Em todos os outros casos, a IOException é lançada. Para resolver este problema, sugiro ao arquivo aberto em modo de leitura e escrita: RandomAccessFile (fileName, "rw")
Dmitry Mitskevich
5
Eu poderia imaginar outras fontes para ler apenas uma parte do arquivo (o arquivo está em um compartilhamento de rede ...) readFully () tem o contrato que você está procurando.
precisa
3
Lembre-se de que o RandomAccessFile não é seguro para threads. Portanto, a sincronização pode ser necessária em alguns casos.
bancer
@DmitryMitskevich Também existem outros casos, em sistemas de arquivos que possivelmente não estão em conformidade. por exemplo, ler "arquivos" em / proc / on linux pode causar leituras curtas (ou seja, você precisa de um loop para ler tudo)
nos
78
Basicamente, você tem que ler na memória. Abra o arquivo, aloque a matriz e leia o conteúdo do arquivo na matriz.
Isto tem alguma cópia desnecessária do conteúdo do arquivo (na verdade, os dados são copiados três vezes: de arquivo para buffer, a partir bufferde ByteArrayOutputStream, a partir ByteArrayOutputStreamda matriz resultante real).
Você também precisa ter certeza de ler apenas na memória arquivos de até um determinado tamanho (isso geralmente depende do aplicativo) :-).
Você também precisa tratar a parte IOExceptionexterna da função.
Outra maneira é esta:
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;}
Isso não tem cópia desnecessária.
FileTooBigExceptioné uma exceção de aplicativo personalizado. A MAX_FILE_SIZEconstante é um parâmetro de aplicação.
Para arquivos grandes, você provavelmente deve pensar em um algoritmo de processamento de fluxo ou usar o mapeamento de memória (consulte java.nio).
A instrução "ios.read (buffer)" no segundo exemplo será lida apenas nos primeiros 4096 bytes do arquivo (assumindo o mesmo buffer de 4k usado no primeiro exemplo). Para o segundo exemplo funcionar, acho que a leitura precisa estar dentro de um loop while que verifica o resultado em -1 (final do arquivo atingido).
Stijn de Witt
Desculpe, ignore minha observação acima, perdi o buffer de configuração da instrução para o tamanho do arquivo. Ainda assim, gosto mais do primeiro exemplo. A leitura de um arquivo inteiro em um buffer de uma só vez não é escalável. Você corre o risco de ficar sem memória quando o arquivo for grande.
Stijn de Witt
A maneira "mais simples" usaria o try-with-resources.
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);...}}
Você também pode usar a API do NIO para fazê-lo. Eu poderia fazer isso com esse código, desde que o tamanho total do arquivo (em bytes) cabesse em um 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();}}
Eu acho que é muito rápido, já que está usando o MappedByteBuffer.
não há absolutamente nenhuma necessidade de usar o mapeamento de memória se você quiser ler o arquivo apenas uma vez e ele acabará usando o dobro da memória que o FileInputStream normal.
james
1
Infelizmente, MappedByteBuffer não é lançado automaticamente.
Tom Hawtin - tackline
2
impressionante, o novo exemplo inclui o printStackTrace, tratamento clássico de exceções quebradas.
james
Eu concordo .. É o material padrão que o eclipse coloca. Acho que devo repetir a exceção!
Amit
Estive comparando o nio para criar um byte [] a partir de um arquivo. Além de usar um buffer direto, ele realmente leva o dobro da memória. Embora seja mais rápido para arquivos muito grandes (cerca de duas vezes mais rápido que um IO em buffer para 200M), parece perder por um fator de 5 para arquivos em torno de 5M.
Chaffers
22
Se você não possui o Java 8, e concorda comigo que é uma má idéia incluir uma enorme biblioteca para evitar a escrita de algumas linhas de código:
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;}
Além disso, coloque numRead dentro do loop. Declare as variáveis no menor escopo válido possível. Colocá-lo fora do loop while é necessário apenas para permitir esse teste complicado "while"; seria melhor fazer o teste para o EOF dentro do loop (e lançar uma EOFException, se ocorrer).
Erickson
throw new IOException("File is too large!");o que devemos fazer quando o arquivo é muito grande? Existe também algum exemplo sobre isso?
Fer
21
Maneira simples de fazer isso:
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);
Você pode explicar aqui? Por que você tem uma discussão?
Muhammad Sadiq
3
Nada de especial, mas você diz mais simples e vejo soluções mais simples -> na minha opinião, não é a mais simples. Talvez tenha sido alguns anos atrás, mas o mundo está mudando. Eu não rotularia minhas próprias soluções com essa afirmação. ;) Se você escreveu "Na minha opinião, o mais simples é .." ou "o mais simples que encontrei .." Não quero incomodá-lo, achei legal comunicar isso.
BlondCode
@ MuhammadSadiq: não importe nada .*, é considerado uma prática ruim.
Ele cobre a caixa de canto em que os arquivos relatam um comprimento de 0, mas ainda têm conteúdo
É altamente otimizado, você obtém uma OutOfMemoryException se tentar ler um arquivo grande antes de tentar carregar o arquivo. (Através do uso inteligente de file.length ())
Usando a mesma abordagem que a resposta do wiki da comunidade, mas mais limpa e compilada imediatamente (abordagem preferida se você não deseja importar as bibliotecas do Apache Commons, por exemplo, no 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();}
já existe uma resposta com esta sugestão de Tom em 2009
Knut Herrmann
7
ReadFully Lê b.length bytes deste arquivo na matriz de bytes, iniciando no ponteiro do arquivo atual. Este método lê repetidamente do arquivo até que o número solicitado de bytes seja lido. Esse método bloqueia até que o número solicitado de bytes seja lido, o final do fluxo seja detectado ou uma exceção seja lançada.
RandomAccessFile f =newRandomAccessFile(fileName,"r");byte[] b =newbyte[(int)f.length()];
f.readFully(b);
Se você deseja ler bytes em um buffer de bytes pré-alocado, esta resposta pode ajudar.
Seu primeiro palpite provavelmente seria usar InputStream read(byte[]) . No entanto, esse método possui uma falha que o torna irracionalmente difícil de usar: não há garantia de que a matriz seja realmente completamente preenchida, mesmo que nenhum EOF seja encontrado.
Em vez disso, dê uma olhada DataInputStream readFully(byte[]). Este é um invólucro para fluxos de entrada e não possui o problema mencionado acima. Além disso, esse método lança quando o EOF é encontrado. Muito melhor.
A maneira a seguir não apenas converte um arquivo java.io.File para um byte [], como também achei a maneira mais rápida de ler em um arquivo, ao testar muitos métodos diferentes de leitura de arquivos Java :
Deixe-me adicionar outra solução sem usar bibliotecas de terceiros. Ele reutiliza um padrão de manipulação de exceção proposto por Scott ( link ). E mudei a parte feia para uma mensagem separada (eu me esconderia em alguma classe 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;}
não use blocos ocos de captura. torna a depuração difícil.
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"
Embora esse código possa fornecer uma solução para a pergunta, é melhor adicionar contexto ao porquê / como ele funciona. Isso pode ajudar os usuários futuros a aprender e aplicar esse conhecimento ao seu próprio código. Também é provável que você tenha um feedback positivo dos usuários na forma de upvotes, quando o código for explicado.
borchvm
Bem, essa é a parte importante que lembrarei nas próximas postagens. Obrigado por suas informações úteis.
Respostas:
Depende do que melhor significa para você. Em termos de produtividade, não reinvente a roda e use o Apache Commons. Qual é aqui
IOUtils.toByteArray(InputStream input)
.fonte
File
parabyte[]
? Estou usando Java6 então não posso usar os métodos NIO :(No JDK 7 você pode usar
Files.readAllBytes(Path)
.Exemplo:
fonte
Desde o JDK 7 - um liner:
Nenhuma dependência externa necessária.
fonte
import java.nio.file.Files;
eimport java.nio.file.Paths;
se ainda não o tiver.Documentação para Java 8: http://docs.oracle.com/javase/8/docs/api/java/io/RandomAccessFile.html
fonte
Basicamente, você tem que ler na memória. Abra o arquivo, aloque a matriz e leia o conteúdo do arquivo na matriz.
A maneira mais simples é algo semelhante a isto:
Isto tem alguma cópia desnecessária do conteúdo do arquivo (na verdade, os dados são copiados três vezes: de arquivo para
buffer
, a partirbuffer
deByteArrayOutputStream
, a partirByteArrayOutputStream
da matriz resultante real).Você também precisa ter certeza de ler apenas na memória arquivos de até um determinado tamanho (isso geralmente depende do aplicativo) :-).
Você também precisa tratar a parte
IOException
externa da função.Outra maneira é esta:
Isso não tem cópia desnecessária.
FileTooBigException
é uma exceção de aplicativo personalizado. AMAX_FILE_SIZE
constante é um parâmetro de aplicação.Para arquivos grandes, você provavelmente deve pensar em um algoritmo de processamento de fluxo ou usar o mapeamento de memória (consulte
java.nio
).fonte
Como alguém disse, o Apache Commons File Utils pode ter o que você está procurando
Exemplo de uso (
Program.java
):fonte
Você também pode usar a API do NIO para fazê-lo. Eu poderia fazer isso com esse código, desde que o tamanho total do arquivo (em bytes) cabesse em um int.
Eu acho que é muito rápido, já que está usando o MappedByteBuffer.
fonte
Se você não possui o Java 8, e concorda comigo que é uma má idéia incluir uma enorme biblioteca para evitar a escrita de algumas linhas de código:
O chamador é responsável por fechar o fluxo.
fonte
fonte
throw new IOException("File is too large!");
o que devemos fazer quando o arquivo é muito grande? Existe também algum exemplo sobre isso?Maneira simples de fazer isso:
fonte
Maneira mais simples para ler bytes do arquivo
fonte
.*
, é considerado uma prática ruim.A Goiaba tem o Files.toByteArray () para lhe oferecer. Tem várias vantagens:
fonte
fonte
Usando a mesma abordagem que a resposta do wiki da comunidade, mas mais limpa e compilada imediatamente (abordagem preferida se você não deseja importar as bibliotecas do Apache Commons, por exemplo, no Android):
fonte
Eu acredito que esta é a maneira mais fácil:
fonte
ReadFully Lê b.length bytes deste arquivo na matriz de bytes, iniciando no ponteiro do arquivo atual. Este método lê repetidamente do arquivo até que o número solicitado de bytes seja lido. Esse método bloqueia até que o número solicitado de bytes seja lido, o final do fluxo seja detectado ou uma exceção seja lançada.
fonte
Se você deseja ler bytes em um buffer de bytes pré-alocado, esta resposta pode ajudar.
Seu primeiro palpite provavelmente seria usar
InputStream read(byte[])
. No entanto, esse método possui uma falha que o torna irracionalmente difícil de usar: não há garantia de que a matriz seja realmente completamente preenchida, mesmo que nenhum EOF seja encontrado.Em vez disso, dê uma olhada
DataInputStream readFully(byte[])
. Este é um invólucro para fluxos de entrada e não possui o problema mencionado acima. Além disso, esse método lança quando o EOF é encontrado. Muito melhor.fonte
A maneira a seguir não apenas converte um arquivo java.io.File para um byte [], como também achei a maneira mais rápida de ler em um arquivo, ao testar muitos métodos diferentes de leitura de arquivos Java :
java.nio.file.Files.readAllBytes ()
fonte
Deixe-me adicionar outra solução sem usar bibliotecas de terceiros. Ele reutiliza um padrão de manipulação de exceção proposto por Scott ( link ). E mudei a parte feia para uma mensagem separada (eu me esconderia em alguma classe FileUtils;))
fonte
fonte
Outra maneira de ler bytes do arquivo
fonte
fonte
Tente o seguinte:
fonte
No JDK8
fonte