【问题标题】:Android: read a GZIP file in the ASSETS folderAndroid:读取资产文件夹中的 GZIP 文件
【发布时间】:2011-01-22 18:42:31
【问题描述】:

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

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

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

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

注意: 使用安卓 1.5

【问题讨论】:

  • 您检查过文件大小了吗?由于 APK 文件是 ZIP 档案,如果该资源无论如何都被压缩,那么 GZIP 可能没有任何价值。
  • 呼应 commonsware,我发现压缩资源对 apk 大小绝对没有影响,因为 apk 已经被压缩。仍然是一个有趣的问题,为什么这不起作用(因为我之前在测试期间已经得到了这样的场景)。
  • int size = fIn.available();

标签: android gzip android-assets gzipinputstream


【解决方案1】:

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

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

【讨论】:

  • 其实并没有解压文件;它只是剥离了.gz 扩展。您仍然需要将输入流包装在 GZIPInputStream 中才能读取它。
  • 在最新的 Android Studio 上仍然会发生.. :P
【解决方案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 是一个 zip 文件 - 此类将把该 zip 中的所有文件解压缩到您的本地文件夹。 我将它用于 NDK。

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

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        【解决方案5】:

        如果您使用AssetManager 而不是Resources,会发生什么情况?示例:

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

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

        【讨论】:

          【解决方案6】:

          尝试查看来自apps-for-android 开源项目的source for Translate,看看是否有帮助。

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

          public void selectRandomWord() {
              BufferedReader fr = null;
              try {
                  GZIPInputStream is =
                          new GZIPInputStream(getResources().openRawResource(R.raw.dictionary));
          

          【讨论】:

          • 我不断收到一个 FileNotFoundException 这是可笑的,因为资源知道该文件存在 R.raw.myfile
          • 嗯,这是一个奇怪的问题。这是在黑暗中拍摄,但可以尝试在 Eclipse 中刷新您的项目并按照stackoverflow.com/questions/2322820/…中所述重新编译@
          猜你喜欢
          • 2018-01-19
          • 2023-03-11
          • 1970-01-01
          • 2012-07-21
          • 2012-03-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-11
          相关资源
          最近更新 更多