I am trying to read a File
from the raw folder in my assets using a FileInputStream
.
This is how I create the FileInputStream
:
AssetManager assetManager = getAssets();
AssetFileDescriptor fileDescriptor = assetManager.openFd(fileName);
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
After that I am trying to read the data from the 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 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?
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()
: 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 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);
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With