I tried to create a RandomAccessFile object from a raw resource file in android resource directory without success.
I'm only able to get a inputstream object from raw resource file.
getResources().openRawResource(R.raw.file);
Is it possible to create a RandomAccessFile object from raw asset file or Do I need to stick with inputstream?
Why not get a new AssetFileDescriptor each time you need a seek? It seems not to be a cpu cycles intensive task (or is it?)
//seek to your first start position
InputStream ins = getAssets().openFd("your_file_name").createInputStream();
isChunk.skip(start);
//read some bytes
ins.read(toThisBuffer, 0, length);
//later on
//seek to a different position, need to openFd again!
//because createInputStream can be called on asset file descriptor only once.
//This resets the new stream to file offset 0,
//so need to seek (skip()) to a new position relative to file beginning.
ins = getAssets().openFd("your_file_name").createInputStream();
ins.skip(start2);
//read some bytes
ins.read(toThatBuffer, 0, length);
I've used this method in my app that needs random access to a 20Mb resource file hundreds of times per second.
It's simply not possible to seek forward and back in an input stream without buffering everything in between into memory. That can be extremely costly, and isn't a scalable solution for reading a (binary) file of some arbitrary size.
You're right: ideally, one would use a RandomAccessFile
, but reading from the resources provides an input stream instead. The suggestion mentioned in the comments above is to use the input stream to write the file to the SD card, and randomly access the file from there. You could consider writing the file to a temporary directory, reading it, and deleting it after use:
String file = "your_binary_file.bin";
AssetFileDescriptor afd = null;
FileInputStream fis = null;
File tmpFile = null;
RandomAccessFile raf = null;
try {
afd = context.getAssets().openFd(file);
long len = afd.getLength();
fis = afd.createInputStream();
// We'll create a file in the application's cache directory
File dir = context.getCacheDir();
dir.mkdirs();
tmpFile = new File(dir, file);
if (tmpFile.exists()) {
// Delete the temporary file if it already exists
tmpFile.delete();
}
FileOutputStream fos = null;
try {
// Write the asset file to the temporary location
fos = new FileOutputStream(tmpFile);
byte[] buffer = new byte[1024];
int bufferLen;
while ((bufferLen = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bufferLen);
}
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {}
}
}
// Read the newly created file
raf = new RandomAccessFile(tmpFile, "r");
// Read your file here
} catch (IOException e) {
Log.e(TAG, "Failed reading asset", e);
} finally {
if (raf != null) {
try {
raf.close();
} catch (IOException e) {}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {}
}
if (afd != null) {
try {
afd.close();
} catch (IOException e) {}
}
// Clean up
if (tmpFile != null) {
tmpFile.delete();
}
}
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