4

如何在 Android 中读取位于“资产”(或资源/原始)文件夹中的 GZIP 文件?

我尝试了以下代码,但我的流大小始终为 1。

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

由于某种原因,大小始终为 1。但如果我不 GZIP 文件,它工作正常。

注意: 使用安卓 1.5

4

6 回答 6

4

从 assets 文件夹中读取 gz 文件时,我遇到了同样的问题。

这是由gz文件的文件名引起的。只需将 yourfile.gz 重命名为其他名称,例如 yourfile.bin。如果Android构建系统认为它是gz,它似乎会自动解压缩文件。

于 2010-08-10T08:18:07.263 回答
3
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 是一个 zip 文件 - 此类将把该 zip 中的所有文件解压缩到您的本地文件夹。我将它用于 NDK。

您可以通过以下方式从 ndk 访问您的文件:/data/data//files/

package = ResLoader 所在的包 filename = raw/resources.zip 中的文件之一

于 2010-03-07T19:21:43.350 回答
2

这是 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.

滥用可用是一个常见的错误——在任何情况下,您都不能假设它会告诉您文件的长度(尽管您已经注意到它有时会这样做)。您想继续调用 read(byte[], int, int) 直到它返回 0。如果您希望长度预先分配一个 byte[],您可能希望创建一个 ByteArrayOutputStream 并在每次阅读时写入,然后在退出循环时从中获取一个 byte[] 。这适用于所有情况下的所有 InputStream。

于 2010-03-07T19:17:43.920 回答
1

构建系统似乎将 .gz 文件视为一种特殊情况,即使它作为原始资源包含在内也是如此。重命名 .gz 文件以具有不同的扩展名,例如 .raw 或 .bin 。

至少对 Android Studio 2.2 有效。我找不到任何文档来确认这是预期的行为,或者更好的是如何防止它,但更改扩展名至少可以解决问题。

于 2016-11-08T21:05:04.787 回答
0

尝试从apps-for-android开源项目中查看Translate的源代码,看看是否有帮助。

他们在 selectRandomWord() 函数 [第 326 行] 中对原始文件使用 GZIPInputStream(源代码粘贴在下面)

public void selectRandomWord() {
    BufferedReader fr = null;
    try {
        GZIPInputStream is =
                new GZIPInputStream(getResources().openRawResource(R.raw.dictionary));
于 2010-03-02T16:26:14.050 回答
0

如果你使用AssetManager代替会发生什么Resources?例子:

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

在内部,Resources只是调用AssetManager;我想知道它是否在某个地方把事情搞砸了。

于 2010-03-02T15:55:08.617 回答