Как переместить / переименовать файл из внутреннего хранилища приложений во внешнее хранилище на Android?

Я загружаю файлы из Интернета и сохраняю потоковые данные во временном файле во внутреннем хранилище моего приложения, предоставляемом getFilesDir () .

Как только загрузка будет завершена, мне нужно переместить файл temp в каталог загрузки в External Memory (обычно SD-карту). По какой-то причине File.renameTo () не работает для этого. Я предполагаю, что есть проблема, потому что это две отдельные файловые системы, но я могу загрузить их прямо на SD-карту, а URI файлов верны.

Есть ли еще простой и быстрый способ переноса этого файла из внутренней памяти на внешний или мне нужно сделать копию потока байтов и удалить оригинал?

Solutions Collecting From Web of "Как переместить / переименовать файл из внутреннего хранилища приложений во внешнее хранилище на Android?"

Чтобы скопировать файлы из внутренней памяти на SD-карту и наоборот, используя следующий фрагмент кода:

public static void copyFile(File src, File dst) throws IOException { FileChannel inChannel = new FileInputStream(src).getChannel(); FileChannel outChannel = new FileOutputStream(dst).getChannel(); try { inChannel.transferTo(0, inChannel.size(), outChannel); } finally { if (inChannel != null) inChannel.close(); if (outChannel != null) outChannel.close(); } } 

И – это работает …

Внутренняя и внешняя память – это две разные файловые системы. Поэтому renameTo () терпит неудачу.

Вам придется скопировать файл и удалить оригинал

После того, как вы скопируете файл (как показывает отличный ответ @barmaley ), не забудьте открыть его в галерее устройства, чтобы пользователь мог просмотреть его позже.

Причина, по которой это нужно сделать вручную, состоит в том, что

Android запускает полное сканирование мультимедиа только при перезагрузке и когда (повторная) установка SD-карты

(Как показано в этом руководстве ).

Более простой способ сделать это – отправить широковещательную рассылку для запуска сканирования:

 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); intent.setData(Uri.fromFile(outputFile)); context.sendBroadcast(intent); 

И вуаля! Теперь вы можете просмотреть свой файл в галерее устройства.

Альтернативой копированию с использованием вашей собственной функции является использование класса библиотеки Apache «FileUtils» в функции copyFile :

 FileUtils.copyFile(src, dst, true); 

Для файла Move лучше всего переименовать его путь с помощью другого пути и имени:

 File from = new File(Environment.getExternalStorage().getAbsolutePath()+"/kaic1/imagem.jpg"); File to = new File(Environment.getExternalStorage().getAbsolutePath()+"/kaic2/imagem.jpg"); from.renameTo(to); 

Сделайте снимок:

  • Это внутренний путь: pathInternal
  • И это внешний путь: pathExternal

Попробуйте этот код:

 public void moveIn (String pathInternal, String pathExternal) { File fInternal = new File (pathInternal); File fExternal = new File (pathExternal); if (fInternal.exists()) { fInternal.renameTo(fExternal); } } 

Произошли некоторые тривиальные модификации кода @ barmaley

 public boolean copyFile(File src, File dst) { boolean returnValue = true; FileChannel inChannel = null, outChannel = null; try { inChannel = new FileInputStream(src).getChannel(); outChannel = new FileOutputStream(dst).getChannel(); } catch (FileNotFoundException fnfe) { Log.d(logtag, "inChannel/outChannel FileNotFoundException"); fnfe.printStackTrace(); return false; } try { inChannel.transferTo(0, inChannel.size(), outChannel); } catch (IllegalArgumentException iae) { Log.d(logtag, "TransferTo IllegalArgumentException"); iae.printStackTrace(); returnValue = false; } catch (NonReadableChannelException nrce) { Log.d(logtag, "TransferTo NonReadableChannelException"); nrce.printStackTrace(); returnValue = false; } catch (NonWritableChannelException nwce) { Log.d(logtag, "TransferTo NonWritableChannelException"); nwce.printStackTrace(); returnValue = false; } catch (ClosedByInterruptException cie) { Log.d(logtag, "TransferTo ClosedByInterruptException"); cie.printStackTrace(); returnValue = false; } catch (AsynchronousCloseException ace) { Log.d(logtag, "TransferTo AsynchronousCloseException"); ace.printStackTrace(); returnValue = false; } catch (ClosedChannelException cce) { Log.d(logtag, "TransferTo ClosedChannelException"); cce.printStackTrace(); returnValue = false; } catch (IOException ioe) { Log.d(logtag, "TransferTo IOException"); ioe.printStackTrace(); returnValue = false; } finally { if (inChannel != null) try { inChannel.close(); } catch (IOException e) { e.printStackTrace(); } if (outChannel != null) try { outChannel.close(); } catch (IOException e) { e.printStackTrace(); } } return returnValue; } 

Вы можете сделать это, используя операции с байтом []

Определите в своем классе:

  public static final String DATA_PATH = Environment.getExternalStorageDirectory().toString() + "/MyAppName/"; 

тогда:

 AssetManager assetManager = context.getAssets(); InputStream in = assetManager.open("data/file.txt"); OutputStream out = new FileOutputStream(DATA_PATH + "data/file.txt"); // Transfer bytes from in to out byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) > 0) { out.write(buf, 0, len); } in.close(); out.close();