Para copiar um arquivo e salvá-lo no caminho de destino, você pode usar o método abaixo.
publicstaticvoid copy(File src,File dst)throwsIOException{InputStream in =newFileInputStream(src);try{OutputStream out =newFileOutputStream(dst);try{// Transfer bytes from in to outbyte[] buf =newbyte[1024];int len;while((len = in.read(buf))>0){
out.write(buf,0, len);}}finally{
out.close();}}finally{
in.close();}}
Na API 19+, você pode usar o Java Automatic Resource Management:
publicstaticvoid copy(File src,File dst)throwsIOException{try(InputStream in =newFileInputStream(src)){try(OutputStream out =newFileOutputStream(dst)){// Transfer bytes from in to outbyte[] buf =newbyte[1024];int len;while((len = in.read(buf))>0){
out.write(buf,0, len);}}}}
Obrigado. depois de bater a cabeça, descobri que faltava permissão para gravar no armazenamento externo. agora funciona bem.
AS
8
@ mohitum007 se o arquivo não conseguir copiar, uma exceção será lançada. use um bloco try catch ao chamar o método
Nima G
9
Se uma exceção for lançada, os fluxos não serão fechados até serem coletados como lixo, e isso não é bom . Considere fechá-los finally.
Pang
1
@Pang. Você está certo. O que é pior: in / out.close () deve ser chamado ou, caso contrário, haverá um vazamento de recursos no sistema operacional subjacente, pois o GC nunca fechará os descritores de arquivos abertos. O GC não pode fechar recursos do SO externos à JVM, como descritores de arquivo ou soquetes. Aqueles deve estar sempre fechado em uma cláusula finalmente programaticamente ou uso try-with-novo recurso sintaxe: docs.oracle.com/javase/tutorial/essential/exceptions/...
earizon
4
Por favor, feche os dois Streams dentro de um finalmente; se houver uma exceção, a memória do seu stream não será coletada.
transferTo pode lançar uma exceção e, nesse caso, você está deixando os fluxos abertos. Assim como Pang e Nima comentaram em resposta aceita.
Viktor Bresan
Além disso, transferTo deve ser chamado dentro do loop, pois não garante que irá transferir o valor total solicitado.
Viktor Brešan 29/11
Eu tentei sua solução e ela falhou com a exceção java.io.FileNotFoundException: /sdcard/AppProj/IMG_20150626_214946.jpg: open failed: ENOENT (No such file or directory)na FileOutputStream outStream = new FileOutputStream(dst);etapa. De acordo com o texto, percebo que o arquivo não existe, então verifico e ligo dst.mkdir();se necessário, mas ainda não ajuda. Eu também tentei verificar dst.canWrite();e ele retornou false. Esta é a fonte do problema? E sim, eu tenho <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>.
Mike B.
1
@ ViktorBrešan Depois de API 19 você pode usar a gestão de recursos automática Java, definindo a entrada e saída fluxos na abertura de sua tentativatry ( FileInputStream inStream = new FileInputStream(src); FileOutputStream outStream = new FileOutputStream(dst) ) {
AlbertMarkovski
Existe alguma maneira de fazer com que esta solução publique seu progresso para onProgressUpdateque eu possa mostrá-la em uma ProgressBar? Na solução aceita, posso calcular o progresso no loop while, mas não consigo ver como fazê-lo aqui.
Não é tão simples se o seu arquivo vier de uma intenção da Galeria Uri.
AjahnCharles
Leia os comentários abaixo dessa resposta: "Esta resposta é ativamente prejudicial e não merece os votos que obtém. Falha se o Uri for um conteúdo: // ou qualquer outro Uri que não seja de arquivo." (Eu fiz upvote - Eu só queria esclarecer que não é uma bala de prata)
AjahnCharles
5
Aqui está uma solução que realmente fecha os fluxos de entrada / saída se ocorrer um erro durante a cópia. Esta solução utiliza os métodos apache Commons IO IOUtils para copiar e manipular o fechamento de fluxos.
publicvoid copyFile(File src,File dst){InputStream in =null;OutputStream out =null;try{
in =newFileInputStream(src);
out =newFileOutputStream(dst);IOUtils.copy(in, out);}catch(IOException ioe){Log.e(LOGTAG,"IOException occurred.", ioe);}finally{IOUtils.closeQuietly(out);IOUtils.closeQuietly(in);}}
Respostas:
Para copiar um arquivo e salvá-lo no caminho de destino, você pode usar o método abaixo.
Na API 19+, você pode usar o Java Automatic Resource Management:
fonte
finally
.Como alternativa, você pode usar o FileChannel para copiar um arquivo. Ele pode ser mais rápido do que o método de cópia byte ao copiar um arquivo grande. Você não pode usá-lo se o seu arquivo tiver mais de 2 GB.
fonte
java.io.FileNotFoundException: /sdcard/AppProj/IMG_20150626_214946.jpg: open failed: ENOENT (No such file or directory)
naFileOutputStream outStream = new FileOutputStream(dst);
etapa. De acordo com o texto, percebo que o arquivo não existe, então verifico e ligodst.mkdir();
se necessário, mas ainda não ajuda. Eu também tentei verificardst.canWrite();
e ele retornoufalse
. Esta é a fonte do problema? E sim, eu tenho<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
.try ( FileInputStream inStream = new FileInputStream(src); FileOutputStream outStream = new FileOutputStream(dst) ) {
onProgressUpdate
que eu possa mostrá-la em uma ProgressBar? Na solução aceita, posso calcular o progresso no loop while, mas não consigo ver como fazê-lo aqui.Extensão Kotlin para ele
fonte
contentResolver.openInputStream(uri)
.Eles funcionaram bem para mim
fonte
Isso é simples no Android O (API 26), como você vê:
fonte
Pode ser tarde demais para uma resposta, mas a maneira mais conveniente é usar
FileUtils
éstatic void copyFile(File srcFile, File destFile)
por exemplo, foi o que eu fiz
`
`
fonte
Muito mais simples agora com Kotlin:
true
oufalse
é para substituir o arquivo de destinohttps://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/copy-to.html
fonte
Aqui está uma solução que realmente fecha os fluxos de entrada / saída se ocorrer um erro durante a cópia. Esta solução utiliza os métodos apache Commons IO IOUtils para copiar e manipular o fechamento de fluxos.
fonte
no kotlin, apenas:
fonte