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

Mik*_*mov 5 java android assets fileinputstream

我正在尝试File使用FileInputStream.

这就是我创建的方式FileInputStream

AssetManager assetManager = getAssets();
AssetFileDescriptor fileDescriptor = assetManager.openFd(fileName);
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
Run Code Online (Sandbox Code Playgroud)

之后,我试图从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();
Run Code Online (Sandbox Code Playgroud)

但这不起作用。出于某种原因,fileChannel.size()返回了一个巨大的数字。我有一个正好 13 个字节长的测试文件,但fileChannel.size()返回 1126498!此外,如果我忽略大小并开始读取返回的字节,则根本不匹配我的测试文件!

那么这里发生了什么?有没有办法解决这个问题?

Xav*_*ler 4

当您的应用程序编译时,所有资源都被打包到本质上是一个大的File. 要仅获取您想要读取的数据,File您必须使用getStartOffset()和。从文档中:getDeclaredLength()AssetFileDescriptor

  • 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);
Run Code Online (Sandbox Code Playgroud)

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

if(declaredLength == AssetFileDescriptor.UNKNOWN_LENGTH) {
    declaredLength = fileChannel.size() - startOffset;
}
Run Code Online (Sandbox Code Playgroud)