我尝试从android资源目录中的原始资源文件创建一个RandomAccessFile对象,但没有成功。
我只能从原始资源文件中获取输入流对象。
getResources().openRawResource(R.raw.file);
是否可以从原始资产文件创建RandomAccessFile对象,或者我是否需要坚持使用输入流?
答案 0 :(得分:1)
根本不可能在输入流中向前和向后搜索而不将其间的所有内容缓冲到内存中。这可能是非常昂贵的,并且不是用于读取任意大小的(二进制)文件的可扩展解决方案。
你是对的:理想情况下,人们会使用RandomAccessFile
,但是从资源中读取会提供输入流。上面评论中提到的建议是使用输入流将文件写入SD卡,并从那里随机访问该文件。您可以考虑将文件写入临时目录,读取并在使用后删除它:
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();
}
}
答案 1 :(得分:0)
为什么每次需要搜索时都不获取新的AssetFileDescriptor?似乎不是cpu周期密集的任务(或者是吗?)
//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);
我在需要每秒随机访问20Mb资源文件数百次的应用中使用了这种方法。