FileChannel returns the incorrect file size of the Assets folder Chinese
I’m trying to use FileInputStream
to read a File
from the original folder in my Assets.
This is how I created FileInputStream
:
AssetManager assetManager = getAssets();
AssetFileDescriptor fileDescriptor = assetManager.openFd(fileName);
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
After that, I tried reading data from File
like this:
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();
But it won’t work. For some reason, fileChannel.size()
returns a huge number. I have a test file that is exactly 13 bytes long, but fileChannel.size()
returns 1126498! Also, if I ignore the size and start reading the returned bytes, it doesn’t match my test file at all!
So what’s going on here? Is there any way to fix this?
Solution
When your application is compiled, all resources are packaged into what is essentially a large file
. To get data for only one File
that you want to read, you must use the
. From >documentation :getStartOffset
() and getDeclaredLength()
Assets file descriptors
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.
So, instead of reading the entire File
from start to finish, it is better to start reading data from the index returned by getStartOffset()
and need to read as many bytes as getDeclaredLength().
Try something like this:
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
MappedByteBuffer mappedByteBuffer = fileChannel.map(
FileChannel.MapMode.READ_ONLY,
startOffset,
declaredLength);
If you want to consider the case where getDeclaredLength()
returns UNKNOWN_LENGTH
, you can do this:
if(declaredLength == AssetFileDescriptor.UNKNOWN_LENGTH) {
declaredLength = fileChannel.size() - startOffset;
}