FileChannel在assets文件夹中返回的文件大小错误

5

我正在尝试使用FileInputStream从我的资产中的原始文件夹读取一个File

这是我创建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()返回了1126498!除此之外,如果我忽略文件大小,直接开始读取返回的字节,它们根本不匹配我的测试文件!
那么这里发生了什么?我能否解决这个问题?

为什么要花那么大的力气读取13个字节?为什么不直接使用FileInputStream?文件中的源代码和字节码比文件中的字节还要多。 - user207421
@EJP 我需要在我的应用程序中从文件中读取80K个整数,这就是为什么我需要nio。 - Mike Herasimov
1个回答

4
当你的应用程序被编译时,所有资源都被打包成一个大的文件。要获取想要读取的文件的数据,你需要使用AssetFileDescriptorgetStartOffset()getDeclaredLength()方法来获取该文件的数据。从文档中得知:
  • getStartOffset():返回此资产条目数据开始的字节偏移量。
  • getDeclaredLength():返回构建AssetFileDescriptor时声明的实际字节数。如果长度未声明,则为UNKNOWN_LENGTH,意味着应读取数据到文件结尾。

所以,你不需要从头到尾读取整个File,而只需要从getStartOffset()返回的索引处开始读取数据,并且需要读取getDeclaredLength()返回的字节数。可以尝试像这样做:
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
MappedByteBuffer mappedByteBuffer = fileChannel.map(
        FileChannel.MapMode.READ_ONLY, 
        startOffset, 
        declaredLength);

如果您想考虑 getDeclaredLength() 返回 UNKNOWN_LENGTH 的情况,您可以这样做:
if(declaredLength == AssetFileDescriptor.UNKNOWN_LENGTH) {
    declaredLength = fileChannel.size() - startOffset;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接