Android: read a GZIP file in the ASSETS folder

后端 未结 6 1359
不思量自难忘°
不思量自难忘° 2021-01-06 08:07

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.



        
相关标签:
6条回答
  • 2021-01-06 08:19

    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.

    0 讨论(0)
  • 2021-01-06 08:24

    Try looking at the source for Translate from apps-for-android open source project and see if that helps at all.

    They use GZIPInputStream on a raw file in their selectRandomWord() function [line 326] (source pasted below)

    public void selectRandomWord() {
        BufferedReader fr = null;
        try {
            GZIPInputStream is =
                    new GZIPInputStream(getResources().openRawResource(R.raw.dictionary));
    
    0 讨论(0)
  • 2021-01-06 08:27

    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.

    0 讨论(0)
  • 2021-01-06 08:30

    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.

    0 讨论(0)
  • 2021-01-06 08:34
    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

    0 讨论(0)
  • 2021-01-06 08:43

    What happens if you use AssetManager instead of Resources? Example:

    InputStream is = mContext.getAssets().open("myfilegz");
    GZIPInputStream fIn = new GZIPINputStream(is);
    

    Internally, Resources is just calling AssetManager; I wonder if somewhere along the way it musses things up.

    0 讨论(0)
提交回复
热议问题