在现代移动设备中,文件系统常常被用作数据库或替代RMS(Record Management System)的存储方式。然而,在三星设备上,当尝试跳转到文件的某个特定位置时,会遇到一些限制。这通常发生在需要读取文件并将其内容作为持久化存储时。
通常情况下,打开和读取文件的操作如下:
m_fc = (FileConnection)Connector.open(myFileFullPath, Connector.READ_WRITE);
InputStream is = m_fc.openInputStream();
byte[] myData = new byte[SOME_SIZE];
is.read(myData);
但是,如果需要跳转到文件的某个特定位置,比如在文件中保存记录或使用它作为持久化存储,那么可能想要保存文件的大小,并在请求时直接跳转到指定位置:
m_fc = (FileConnection)Connector.open(myFileFullPath, Connector.READ_WRITE);
DataInputStream dis = m_fc.openDataInputStream();
int indexSize = dis.readInt();
// 将索引表读入内存,将索引如1,2转换为文件中的偏移量
m_index = new PersistenceIndex(indexSize, dis);
dis.close();
// ... 稍后在代码中
Object getPersistentObject(int index) throws IOException {
DataInputStream dis = m_fc.openDataInputStream();
long offset = m_index.convert(index);
dis.skip(index);
MyObject obj = new MyObject();
obj.RecoverFromStream(dis);
return obj;
}
代码中加粗的部分显示了问题所在。在三星设备上,单个skip命令无法正确跳转到指定位置!已从三星官方确认了这个问题,它存在于固件中。为了解决这个问题,可以反复跳过InputStream。这个函数返回的值将告诉这次调用跳过了多少,所以只需累加直到达到所需的位置。以下是实现这一功能的示例代码(来自原文):
private long skipFully(InputStream stream, int offset) throws IOException {
long skippedBytes = stream.skip(offset);
Logger.info(m_name + ": skipFully : skippedBytes - " + skippedBytes);
long totalSkip = skippedBytes;
int count = MAX_ITERATION;
if (skippedBytes != offset) {
offset -= skippedBytes;
Logger.info(m_name + ": skipFully : still has - " + offset + " to read");
while (offset > 0 && count > 0) {
skippedBytes = stream.skip(offset);
Logger.info(m_name + ": skipFully : skippedBytes was - " + skippedBytes + " for offset - " + offset);
totalSkip += skippedBytes;
offset -= skippedBytes;
count--;
}
}
Logger.info(m_name + ": skipFully : totally skipped on: " + totalSkip);
return totalSkip;
}