FileChannel返回文件的错误的文件大小的资产文件夹文件大小、文件夹、错误、资产

2023-09-05 07:52:04 作者:予囚

我想读文件从使用原始文件夹在我的资产的FileInputStream

I am trying to read a File from the raw folder in my assets using a FileInputStream.

这是我如何创建的FileInputStream

AssetManager assetManager = getAssets();
AssetFileDescriptor fileDescriptor = assetManager.openFd(fileName);
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());

之后,我想读的文件这样的数据:

FileChannel fileChannel = inputStream.getChannel();

MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
IntBuffer intBuffer = mappedByteBuffer.asIntBuffer();

int[] array = new int[intBuffer.limit()];
intBuffer.get(array);

inputStream.close();
fileChannel.close();

但是,这并不正常工作。出于某种原因, fileChannel.size()返回一个巨大的数字。我有一个测试文件,这也正是13个字节长,但​​ fileChannel.size()返回1​​126498!而另外,如果我不理规模和刚刚开始阅读返回的字节数不匹配我的测试文件了!

But this does not work. For some reason fileChannel.size() returns a huge number. I have a test file which is exactly 13 bytes long, but fileChannel.size() returns 1126498! And additionally if I ignore the size and just start reading the returned bytes don't match my test file at all!

那么,什么是怎么回事?而且是有办法可以解决这个问题?

So what is going on here? And is there a way I can fix this?

推荐答案

当你的应用程序编译所有资源一起打包成什么本质上是一个大的文件。为了得到一个文件只是数据你想阅读你必须使用 getStartOffset() getDeclaredLength() AssetFileDescriptor 。从 文件 :

When your app is compiled all resources are packaged together into what is essentially one big File. To get just the data of the one File you want to read you have to use getStartOffset() and getDeclaredLength() of the AssetFileDescriptor. From the documentation:

   getStartOffset():返回字节偏移,其中该资产录入的数据开始    getDeclaredLength():返回与被宣布当AssetFileDescriptor构建的实际字节数。会是    UNKNOWN_LENGTH 如果长度未声明的,也就是说数据应该是   读该文件的末尾。    getStartOffset(): Returns the byte offset where this asset entry's data starts. getDeclaredLength(): Return the actual number of bytes that were declared when the AssetFileDescriptor was constructed. Will be UNKNOWN_LENGTH if the length was not declared, meaning data should be read to the end of the file.

因此​​,而不是仅仅阅读了整个文件从开始到结束,你只需要读起由 getStartOffset返回的索引处的数据() ,你需要的是由返回读取的字节数getDeclaredLength()。尝试是这样的:

So instead of just reading the whole File from start to finish you just need to read the data starting at the index returned by getStartOffset() and you need to read as many bytes as are returned by getDeclaredLength(). Try something like this:

long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
MappedByteBuffer mappedByteBuffer = fileChannel.map(
        FileChannel.MapMode.READ_ONLY, 
        startOffset, 
        declaredLength);

如果你想解释的情况下,其中 getDeclaredLength()返回 UNKNOWN_LENGTH 你可以这样做:

If you want to account for the case in which getDeclaredLength() returns UNKNOWN_LENGTH you can just do this:

if(declaredLength == AssetFileDescriptor.UNKNOWN_LENGTH) {
    declaredLength = fileChannel.size() - startOffset;
}