3

我在 res/raw 中有一个未压缩的二进制文件,我正在以这种方式阅读:

public byte[] file2Bytes (int rid) {
    byte[] buffer = null;
    try {
        AssetFileDescriptor afd = res.openRawResourceFd(rid);
        FileInputStream in = new FileInputStream(afd.getFileDescriptor());
        int len = (int)afd.getLength();
        buffer = new byte[len];
        in.read(buffer, 0, len);
        in.close();
    } catch (Exception ex) {
        Log.w(ACTNAME, "file2Bytes() fail\n"+ex.toString());
        return null;
    }
    return buffer;
}  

但是,buffer没有包含它应该包含的内容。源文件是 1024 个基本上随机的字节(二进制密钥)。但是buffer,当写出来和检查时,就不一样了。在开头的不可打印字节中出现了“res/layout/main.xml”(文字路径),然后再往下是来自 res/raw 的另一个文件的部分文本内容。O_O?

一段时间后,我很生气,我尝试:

            AssetFileDescriptor afd = res.openRawResourceFd(rid);
            //FileInputStream in = new FileInputStream(afd.getFileDescriptor());
            FileInputStream in = afd.createInputStream(); 

Presto,我得到了正确的内容——这很容易重现。

所以相关的 API 文档如下:

公共文件描述符 getFileDescriptor ()

返回可用于读取文件中数据的 FileDescriptor。

公共文件输入流创建输入流()

为此资产创建并返回一个新的自动关闭输入流。这将返回完整的资产 AssetFileDescriptor.AutoCloseInputStream 或底层 ParcelFileDescriptor.AutoCloseInputStream,具体取决于对象是代表完整文件还是文件的子部分。您应该只为特定资产调用一次。

为什么从 getFileDescriptor() 构造的 FileInputStream() 最终会产生垃圾,而 createInputStream() 会提供正确的访问权限?

4

2 回答 2

4

根据 pskink 的评论,由 AssetFileDescriptor() 返回的 FileDescriptor 显然不是仅指文件的 fd——它可能指的是任何 bundle/parcel/conglomeration aapt 对资源所做的事情。

        AssetFileDescriptor afd = res.openRawResourceFd(rid);
        FileInputStream in = new FileInputStream(afd.getFileDescriptor());
        in.skip(afd.getStartOffset());           

原来是FileInputStream in = afd.createInputStream()版本的等价物。

我想“创建”(新事物)和“获取”(现有事物)之间的区别有一个暗示。:/

于 2013-11-03T15:01:43.560 回答
0

AssetFileDescriptor 可以被认为是整个包的资产数据的入口点。

我遇到了同样的问题并最终解决了。

如果要从 AssetFileDescriptor 手动创建流,则必须跳过 n 个字节到请求的资源。就像您正在通过一个大文件中的所有可用文件进行分页。

感谢 pskink!我查看了我想要获取的 jpg 图像的十六进制内容,它以 -1 开头。问题是,有两个 jpg 图像。我不知道,所以我随意跳过了76L字节。拿到第一张图了!

于 2015-05-17T16:08:45.360 回答