Aby skopiować plik i zapisać go na docelowej ścieżce, możesz użyć poniższej metody.
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();}}
W API 19+ możesz używać automatycznego zarządzania zasobami Java:
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);}}}}
Dziękuję Ci. po tym, jak uderzyłem się w głowę, okazało się, że problemem jest brak uprawnień do zapisu w pamięci zewnętrznej. teraz działa dobrze.
AS
8
@ mohitum007 jeśli plik nie zostanie skopiowany, zgłoszony zostanie wyjątek. użyj wywołania metody try catch.
Nima G
9
Jeśli zostanie zgłoszony wyjątek, strumienie nie zostaną zamknięte, dopóki nie zostaną usunięte, a to nie jest dobre . Rozważ zamknięcie ich finally.
Pang
1
@Ostry ból. Masz rację. Co gorsza, należy wywołać metodę in / out.close (), w przeciwnym razie nastąpi przeciek zasobów w podstawowym systemie operacyjnym, ponieważ GC nigdy nie zamknie otwartych deskryptorów plików. GC nie może zamykać zasobów systemu operacyjnego poza JVM, takich jak deskryptory plików lub gniazda. Muszą one zawsze być programowo zamknięte w klauzuli wreszcie lub użyj nowej składni try-with-resource: docs.oracle.com/javase/tutorial/essential/exceptions/…
earizon
4
Proszę zamknąć oba strumienie w końcu, jeśli istnieje wyjątek, pamięć strumieni nie zostanie zebrana.
transferTo może zgłosić wyjątek, w którym to przypadku pozostawiasz otwarte strumienie. Tak jak Pang i Nima skomentowali w zaakceptowanej odpowiedzi.
Viktor Brešan
TransferTo powinien być również wywoływany wewnątrz pętli, ponieważ nie gwarantuje, że przekaże całkowitą żądaną kwotę.
Viktor Brešan
Wypróbowałem twoje rozwiązanie i dla mnie nie działa, z wyjątkiem java.io.FileNotFoundException: /sdcard/AppProj/IMG_20150626_214946.jpg: open failed: ENOENT (No such file or directory)tego FileOutputStream outStream = new FileOutputStream(dst);kroku. Zgodnie z tekstem zdaję sobie sprawę, że plik nie istnieje, więc sprawdzam go i w dst.mkdir();razie potrzeby dzwonię , ale nadal nie pomaga. Próbowałem też sprawdzić dst.canWrite();i wrócił false. Czy to może być przyczyną problemu? I tak mam <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>.
Mike B.
1
@ ViktorBrešan Po API 19 można korzystać z automatycznego zarządzania zasobami Java, definiując strumienie wejściowe i wyjściowe na początku próbytry ( FileInputStream inStream = new FileInputStream(src); FileOutputStream outStream = new FileOutputStream(dst) ) {
AlbertMarkovski
Czy jest jakiś sposób, aby to rozwiązanie opublikowało swoje postępy onProgressUpdate, aby mógłbym pokazać go w pasku postępu? W przyjętym rozwiązaniu mogę obliczyć postęp w pętli while, ale nie widzę tutaj, jak to zrobić.
To najbardziej zwięzła, ale elastyczna odpowiedź. Prostsze odpowiedzi nie uwzględniają identyfikatorów URI otwieranych za pośrednictwem contentResolver.openInputStream(uri).
Nie takie proste, jeśli Twój plik pochodzi z Uri przeznaczonego dla galerii.
AjahnCharles
Przeczytaj poniższe komentarze tej odpowiedzi: „Ta odpowiedź jest aktywnie szkodliwa i nie zasługuje na głosy, które otrzyma. Nie powiedzie się, jeśli Uri jest zawartością: // lub innym nie-plikowym Uri”. (Przegłosowałem - chciałem tylko wyjaśnić, że to nie srebrna kula)
AjahnCharles
5
Oto rozwiązanie, które faktycznie zamyka strumienie wejściowe / wyjściowe, jeśli podczas kopiowania wystąpi błąd. To rozwiązanie wykorzystuje metody apache Commons IO IOUtils do kopiowania i obsługi zamykania strumieni.
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);}}
Odpowiedzi:
Aby skopiować plik i zapisać go na docelowej ścieżce, możesz użyć poniższej metody.
W API 19+ możesz używać automatycznego zarządzania zasobami Java:
źródło
finally
.Alternatywnie możesz użyć FileChannel, aby skopiować plik. To może być szybsze niż metoda kopiowania bajtów podczas kopiowania dużego pliku. Nie możesz go jednak użyć, jeśli Twój plik jest większy niż 2 GB.
źródło
java.io.FileNotFoundException: /sdcard/AppProj/IMG_20150626_214946.jpg: open failed: ENOENT (No such file or directory)
tegoFileOutputStream outStream = new FileOutputStream(dst);
kroku. Zgodnie z tekstem zdaję sobie sprawę, że plik nie istnieje, więc sprawdzam go i wdst.mkdir();
razie potrzeby dzwonię , ale nadal nie pomaga. Próbowałem też sprawdzićdst.canWrite();
i wróciłfalse
. Czy to może być przyczyną problemu? I tak mam<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
.try ( FileInputStream inStream = new FileInputStream(src); FileOutputStream outStream = new FileOutputStream(dst) ) {
onProgressUpdate
, aby mógłbym pokazać go w pasku postępu? W przyjętym rozwiązaniu mogę obliczyć postęp w pętli while, ale nie widzę tutaj, jak to zrobić.Rozszerzenie Kotlin dla niego
źródło
contentResolver.openInputStream(uri)
.Te działały dla mnie dobrze
źródło
Jest to proste w Androidzie O (API 26), jak widać:
źródło
Na odpowiedź może być za późno, ale najwygodniejszym sposobem jest użycie
FileUtils
„sstatic void copyFile(File srcFile, File destFile)
np. to zrobiłem
`
`
źródło
O wiele prostsze teraz dzięki Kotlin:
true
lubfalse
służy do zastąpienia pliku docelowegohttps://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-file/copy-to.html
źródło
Oto rozwiązanie, które faktycznie zamyka strumienie wejściowe / wyjściowe, jeśli podczas kopiowania wystąpi błąd. To rozwiązanie wykorzystuje metody apache Commons IO IOUtils do kopiowania i obsługi zamykania strumieni.
źródło
w kotlin, po prostu:
źródło