Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to safely save a file to disk in android?

I have written an android app that saves (potentially) large files to the SD Card. Occasionally I get an IOException during the write operation which causes the file to be left in a corrupt state. Based on the answer to this question:

Question: How to safely write to a file?

the strategy I should use is to create a temporary file and then copy this file once the write has completed. My questions are:

1) Is this the safest approach on Android? (e.g. Can you copy files on the android sd card and if so is the operation atomic?)

2) In an embedded system with limited resources (disk space) does anyone know of another strategy for safely writing to a disk? (instead of creating two large files)

Thanks

like image 909
brif Avatar asked Oct 29 '11 17:10

brif


People also ask

Where do files save on Android?

Internal Storage in Android. Files can be saved directly in the “internal” storage of the device. When the files are saved in the internal storage, they are automatically set to private. These files are set to private so they cannot be used by other applications.

How do I save files to my device?

On the file menu, tap Save As. You can save your files locally to your device or save them to the cloud so you can share with others easily.


2 Answers

I know this is too late to answer, but will help anyone who come across this will find it helpful.

You need to use AtomicFile.

Following code snippet may help.

public void writeFile(File file, byte[] data) {
    AtomicFile aFile = new AtomicFile(file);
    FileOutputStream fos = null;

    try {
        fos = aFile.startWrite();
        fos.write(data);
        // Close stream and commit new data.
        aFile.finishWrite(fos);
        fos = null;
    } catch (IOException e) {
        Log.e(TAG, "Cannot write file " + file.getPath(), e);
    } finally {
        if (fos != null) {
            // Something went wrong.
            // Close stream and roll back data.
            aFile.failWrite(fos);
        }
    }
}
like image 196
Pawan Avatar answered Sep 25 '22 08:09

Pawan


The typical way to safely create a file on most reasonable platforms (Linux/Android is one of them) is to create a temporary file and then rename the file, as mentioned in the question & answers that you linked to. Note the emphasis on rename; renaming a file is usually an atomic operation within the same filesystem, copying one is not. In addition, this method only requires enough space for a single copy of the data.

Therefore you create a file in the target directory using a temporary name and then use File.renameTo() to give it a proper name. By using a standard naming convention for the temporary files you can always find and delete them, even if your application terminates unexpectedly due to e.g. a device power-off.

If you are really paranoid, you may want to insert a few calls to FileDescriptor.sync() or equivalent...

EDIT:

BTW, you do not mention what kind of IOException your are getting and whether you have tracked down its cause. If it's due to insufficient space, fine, but if we are talking about a faulty SD card, then there is no such thing as "safe" in this case.

EDIT 2:

In order to check the available free space, you can create a File object for the destination directory (i.e. the directory where your file will end up) and call File.getFreeSpace(). Keep in mind that this check does not provide any guarantees - you may still end up without enough space if e.g. another process writes data to the medium.

like image 42
thkala Avatar answered Sep 22 '22 08:09

thkala