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

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

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

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

Ответы [ 8 ]

82 голосов
/ 23 января 2011

Для копирования файлов из внутренней памяти на 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();
    }
}

И - это работает ...

12 голосов
/ 23 января 2011

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

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

10 голосов
/ 08 декабря 2015

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

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

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

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

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

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

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

3 голосов
/ 06 марта 2014

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

FileUtils.copyFile(src, dst, true);
0 голосов
/ 16 ноября 2015

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

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

    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();
0 голосов
/ 05 августа 2015

Представьте, что:

  • Это внутренний путь: 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);
    }
}
0 голосов
/ 11 февраля 2015

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

File from = new File(Environment.getExternalStorage().getAbsolutePath()+"/kaic1/imagem.jpg");
File to = new File(Environment.getExternalStorage().getAbsolutePath()+"/kaic2/imagem.jpg");
from.renameTo(to);
0 голосов
/ 22 октября 2013

Сделал несколько тривиальных изменений в коде @ 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;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...