如何在 Android 中读取位于“资产”(或资源/原始)文件夹中的 GZIP 文件?
我尝试了以下代码,但我的流大小始终为 1。
GZIPInputStream fIn = new GZIPInputStream(mContext.getResources().openRawResource(R.raw.myfilegz));
int size = fIn.available();
由于某种原因,大小始终为 1。但如果我不 GZIP 文件,它工作正常。
注意: 使用安卓 1.5
如何在 Android 中读取位于“资产”(或资源/原始)文件夹中的 GZIP 文件?
我尝试了以下代码,但我的流大小始终为 1。
GZIPInputStream fIn = new GZIPInputStream(mContext.getResources().openRawResource(R.raw.myfilegz));
int size = fIn.available();
由于某种原因,大小始终为 1。但如果我不 GZIP 文件,它工作正常。
注意: 使用安卓 1.5
从 assets 文件夹中读取 gz 文件时,我遇到了同样的问题。
这是由gz文件的文件名引起的。只需将 yourfile.gz 重命名为其他名称,例如 yourfile.bin。如果Android构建系统认为它是gz,它似乎会自动解压缩文件。
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 中的文件之一
这是 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。
构建系统似乎将 .gz 文件视为一种特殊情况,即使它作为原始资源包含在内也是如此。重命名 .gz 文件以具有不同的扩展名,例如 .raw 或 .bin 。
至少对 Android Studio 2.2 有效。我找不到任何文档来确认这是预期的行为,或者更好的是如何防止它,但更改扩展名至少可以解决问题。
尝试从apps-for-android开源项目中查看Translate的源代码,看看是否有帮助。
他们在 selectRandomWord() 函数 [第 326 行] 中对原始文件使用 GZIPInputStream(源代码粘贴在下面)
public void selectRandomWord() {
BufferedReader fr = null;
try {
GZIPInputStream is =
new GZIPInputStream(getResources().openRawResource(R.raw.dictionary));
如果你使用AssetManager代替会发生什么Resources?例子:
InputStream is = mContext.getAssets().open("myfilegz");
GZIPInputStream fIn = new GZIPINputStream(is);
在内部,Resources只是调用AssetManager;我想知道它是否在某个地方把事情搞砸了。