• 3
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

I am downloading files from the internet and saving the streaming data to a temp file in my app's internal storage given by getFilesDir().

Once the download is complete, I need to move the temp file to my download directory on External Memory (usually an SD Card). For some reason though, File.renameTo() isn't working for this. I'm guessing there's a problem because it's two separate file systems, but I can still download directly to the SD Card and the file URIs are correct.

Is there another simple and quick way to transfer that file from internal memory to external or do I have to do a byte stream copy and delete the original?

    • old question, but to answer why file.renameTo() didn't work, it is because the function requires the locations to be on the same mount-point, and sdcard and internal are different locations: "Both paths be on the same mount point. On Android, applications are most likely to hit this restriction when attempting to copy between internal storage and an SD card." developer.android.com/reference/java/io/…

To copy files from internal memory to SD card and vice-versa using following piece of code:

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();
    }
}

And - it works...

  • 84
Reply Report
      • 1
    • @barmaley: What about folder?? Instead of file. I have 3 folders and i want to cut-paste it to new location. But it shows an error at line FileChannel inChannel = new FileInputStream(src).getChannel(); saying filenotfound exception. though file exists. :( Any solution to this?
      • 1
    • Don't you have to close the results from new FileInputStream(src) and new FileOutputStream(dst) which don't even have a reference here?

After you copy the file (as @barmaley's great answer shows), don't forget to expose it to the device's gallery, so the user can view it later.

The reason why it has to be done manually is that

Android runs a full media scan only on reboot and when (re)mounting the SD card

(as this guide shows).

The easier way to do this is by sending a broadcast for the scanning to be invoked:

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

And voila! You can now view your file in the device's gallery.

  • 10
Reply Report

An alternative to the copying using your own function is to use Apache's library's class "FileUtils" , in the function called copyFile :

FileUtils.copyFile(src, dst, true);
  • 3
Reply Report

Did some trivial modifications to @barmaley's code

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;
    }
  • 0
Reply Report
      • 1
    • Old answer, but I have to caution that this is worse for the modifications. It's worse because it actively hides error conditions. It may appear convenient, but utility functions are not in a position to know whether callers need to distinguish between FileNotFound, NonWritableChannel, etc. It makes downstream logic necessarily fuzzy.

Picture that:

  • This is internal path : pathInternal
  • And this is external path : pathExternal

Try with this code:

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

You can do it using operations with byte[]

define in your class:

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

then:

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
Reply Report

For Move file best way is Renaming it's path with different path and name example:

File from = new File(Environment.getExternalStorage().getAbsolutePath()+"/kaic1/imagem.jpg");
File to = new File(Environment.getExternalStorage().getAbsolutePath()+"/kaic2/imagem.jpg");
from.renameTo(to);
  • -1
Reply Report
      • 1
    • I tried to copy file from the folder «A» to the folder «B», both are stored on /sdcard/. The problem is that in folder «B» instead of copying file the code creates an empty folder with the name of the file I want to copy, but there is no the file itself. The original file exists, so what is the problem? I give two absolute paths and perform from.renameTo(to);, no exception occurs, but instead of file copy I get an empty folder. There is a needed permission in the manifest file. How to fix an issue?