Android: read a GZIP file in the ASSETS folder

14,572

Solution 1

I met the same problem when reading a gz file from assets folder.

It's caused by the file name of the gz file. Just renaming yourfile.gz to other name like yourfile.bin. It seems Android build system would decompress a file automatically if it thought it's a gz.

Solution 2

public class ResLoader {

    /**
     * @param res
     * @throws IOException
     * @throws FileNotFoundException
     * @throws IOException
     */

    static void unpackResources() throws FileNotFoundException, IOException {
        final int BUFFER = 8192;

        android.content.res.Resources t = TestingE3d.mContext.getResources();

        InputStream fis = t.openRawResource(R.raw.resources);
        if (fis == null)
            return;

        ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis,
                BUFFER));
        ZipEntry entry;
        while ((entry = zin.getNextEntry()) != null) {
            int count;

            FileOutputStream fos = TestingE3d.mContext.openFileOutput(entry
                    .getName(), 0);
            BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);

            byte data[] = new byte[BUFFER];

            while ((count = zin.read(data, 0, BUFFER)) != -1) {
                dest.write(data, 0, count);
                // Log.v("NOTAG", "writing "+count + " to "+entry.getName());
            }
            dest.flush();
            dest.close();
        }
        zin.close();

    }

}

R.raw.resources is a zip file - this class will decompress all files in that zip to your local folder. I use this for NDK.

you can access your fils from ndk through: /data/data//files/

package = package where ResLoader resides filename = one of files that is in raw/resources.zip

Solution 3

this is the documented behavior of InflaterInputStream.available:

http://java.sun.com/javase/6/docs/api/java/util/zip/InflaterInputStream.html#available()

Returns 0 after EOF has been reached, otherwise always return 1.

abusing available is a common mistake --- in no case can you assume that it tells you the length of a file (though it sometimes happens to do so, as you've noticed). you want to keep calling read(byte[], int, int) until it returns 0. if you want the length to allocate a byte[] up front, you probably want to create a ByteArrayOutputStream and write to that each time you read, and then get a byte[] from that when you exit the loop. this works for all InputStreams in all cases.

Solution 4

It seems that the build system treats .gz files as a special case, even when it's included as a raw resource. Rename the .gz file to have a different extension, say .raw or .bin .

Valid at least for Android Studio 2.2 . I can't find any docs to confirm this is expected behaviour or, better, how to prevent it, but changing the extension at least works around the problem.

Share:
14,572
Tawani
Author by

Tawani

Updated on June 25, 2022

Comments

  • Tawani
    Tawani about 2 years

    How can you read GZIP file in Android located in the "ASSETS" (or resources/raw) folder?

    I have tried the following code, but my stream size is always 1.

    GZIPInputStream fIn = new GZIPInputStream(mContext.getResources().openRawResource(R.raw.myfilegz)); 
    int size = fIn.available();
    

    for some reason the size is always 1. But if Idon't GZIP the file, it works fine.

    NOTE: Using Android 1.5

  • Tawani
    Tawani over 14 years
    I keep getting a FileNotFoundException which is ridiculus because the Resources know the file is there is R.raw.myfile
  • snctln
    snctln over 14 years
    hmmm, that is an odd problem. It's a shot in the dark but maybe try refreshing your project in eclipse and recompiling as described on stackoverflow.com/questions/2322820/…
  • Ted Hopp
    Ted Hopp almost 13 years
    Actually, it doesn't decompress the file; it just strips off the .gz extension. You still would need to wrap the input stream in a GZIPInputStream to read it.
  • Pasi Matalamäki
    Pasi Matalamäki almost 6 years
    Still happens on newest Android Studio.. :P