Android - Store inputstream in file

77,464

Solution 1

Here it is, input is your inputStream. Then use same File (name) and FileInputStream to read the data in future.

try {
    File file = new File(getCacheDir(), "cacheFileAppeal.srl");
    try (OutputStream output = new FileOutputStream(file)) {
        byte[] buffer = new byte[4 * 1024]; // or other buffer size
        int read;

        while ((read = input.read(buffer)) != -1) {
            output.write(buffer, 0, read);
        }

        output.flush();
    }
} finally {
    input.close();
}

Solution 2

Simple Function

Try this simple function to neatly wrap it up in:

// Copy an InputStream to a File.
//
private void copyInputStreamToFile(InputStream in, File file) {
    OutputStream out = null;

    try {
        out = new FileOutputStream(file);
        byte[] buf = new byte[1024];
        int len;
        while((len=in.read(buf))>0){
            out.write(buf,0,len);
        }
    } 
    catch (Exception e) {
        e.printStackTrace();
    } 
    finally {
        // Ensure that the InputStreams are closed even if there's an exception.
        try {
            if ( out != null ) {
                out.close();
            }

            // If you want to close the "in" InputStream yourself then remove this
            // from here but ensure that you close it yourself eventually.
            in.close();  
        }
        catch ( IOException e ) {
            e.printStackTrace();
        }
    }
}

Thanks to Jordan LaPrise and his answer.

Solution 3

Kotlin version (tested and no library needed):

fun copyStreamToFile(inputStream: InputStream, outputFile: File) {
    inputStream.use { input ->
        val outputStream = FileOutputStream(outputFile)
        outputStream.use { output ->
            val buffer = ByteArray(4 * 1024) // buffer size
            while (true) {
                val byteCount = input.read(buffer)
                if (byteCount < 0) break
                output.write(buffer, 0, byteCount)
            }
            output.flush()
        }
    }
}

We take advantage of use function which will automatically close both streams at the end.

The streams are closed down correctly even in case an exception occurs.

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html
https://kotlinlang.org/docs/tutorials/kotlin-for-py/scoped-resource-usage.html

Solution 4

A shorter version:

OutputStream out = new FileOutputStream(file);
fos.write(IOUtils.read(in));
out.close();
in.close();

Solution 5

Here is a solution which handles all the Exceptions and is based on the previous answers:

void writeStreamToFile(InputStream input, File file) {
    try {
        try (OutputStream output = new FileOutputStream(file)) {
            byte[] buffer = new byte[4 * 1024]; // or other buffer size
            int read;
            while ((read = input.read(buffer)) != -1) {
                output.write(buffer, 0, read);
            }
            output.flush();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Share:
77,464
Admin
Author by

Admin

Updated on July 05, 2022

Comments

  • Admin
    Admin almost 2 years

    I am retrieveing an XML feed from a url and then parsing it. What I need to do is also store that internally to the phone so that when there is no internet connection it can parse the saved option rather than the live one.

    The problem I am facing is that I can create the url object, use getInputStream to get the contents, but it will not let me save it.

    URL url = null;
    InputStream inputStreamReader = null;
    XmlPullParser xpp = null;
    
    url = new URL("http://*********");
    inputStreamReader = getInputStream(url);
    
    ObjectOutput out = new ObjectOutputStream(new FileOutputStream(new File(getCacheDir(),"")+"cacheFileAppeal.srl"));
    
    //--------------------------------------------------------
    //This line is where it is erroring.
    //--------------------------------------------------------
    out.writeObject( inputStreamReader );
    //--------------------------------------------------------
    out.close();
    

    Any ideas how I can go about saving the input stream so I can load it later.

    Cheers

  • amitavk
    amitavk over 8 years
    Nesting try blocks though?
  • Volodymyr Lykhonis
    Volodymyr Lykhonis over 8 years
    Exception can happen anytime if so you will leak system resources.
  • gMale
    gMale about 7 years
    because it requires IOUtils from Apache commons and that's a heavy weight dependency to add to a mobile app. Most people would rather a solution that relies on standard SDK classes.
  • jk7
    jk7 about 7 years
    out.close() should be in a finally {} block to avoid leaking resources if an exception occurs. Same for in.close() if it performed here, though it is really the responsibility of the caller to close it.
  • Joshua Pinter
    Joshua Pinter about 7 years
    @jk7 You're probably right actually. Take a look at the updated answer.
  • Tim Kist
    Tim Kist over 6 years
    For testing (test and androidTest artifacts), it's fine because it won't get included in app.
  • Hack06
    Hack06 about 6 years
    The "input" variable is an instance of InputStream, not InputStreamReader.
  • CoolMind
    CoolMind almost 5 years
    Sorry, what, if an exception oocurs (for instance, disconnection), can we rethrow the exception to an upper level?
  • CodeToLife
    CodeToLife almost 3 years
    i put implementation 'commons-io:commons-io:2.5 ,synced, but it shows import org.apache.commons.io.FileUtils;'s FileUtils in red?
  • Fahad-Android
    Fahad-Android almost 2 years
    I keep getting "File is empty" exception