FileChannel returns 资产文件夹中文件的文件大小错误

FileChannel returns wrong file size of file in assets folder

我正在尝试使用 FileInputStream.

从我资产中的原始文件夹中读取 File

这就是我创建 FileInputStream:

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

之后,我尝试像这样从 File 中读取数据:

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() returns 一个巨大的数字。我有一个恰好 13 个字节长的测试文件,但是 fileChannel.size() returns 1126498!此外,如果我忽略大小并开始读取返回的字节,则根本不匹配我的测试文件!

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

编译您的应用程序时,所有资源都被打包成一个大文件 File。要仅获取您想阅读的 File 的数据,您必须使用 AssetFileDescriptorgetStartOffset()getDeclaredLength()。来自 documentation:

  • 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.

因此,您不需要从头到尾读取整个 File,您只需读取从 getStartOffset() 返回的索引开始的数据,并且您需要读取返回的字节数通过 getDeclaredLength()。尝试这样的事情:

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

如果您想考虑 getDeclaredLength() returns UNKNOWN_LENGTH 的情况,您可以这样做:

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