RecordStore (RMS) 底層以字節數組存儲,RecordStore.addRecord(byte[]) 無字符集概念。直接存儲 String.getBytes() 會因平台默認編碼差異導致中文亂碼。標準解決方案:使用 DataOutputStream.writeUTF() / DataInputStream.readUTF(),採用 **Modified UTF-8** 格式,跨平台安全。
import java.io.*;
public class RmsCodec {
/** 字符串 → 字節數組 (Modified UTF-8) */
public static byte[] toBytes(String str) {
if (str == null) return new byte[0];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
try {
dos.writeUTF(str);
dos.flush();
return baos.toByteArray();
} catch (IOException e) {
return new byte[0];
} finally {
try { dos.close(); } catch (IOException ignored) {}
try { baos.close(); } catch (IOException ignored) {}
}
}
/** 字節數組 → 字符串 (Modified UTF-8) */
public static String toString(byte[] data) {
if (data == null || data.length == 0) return "";
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
try {
return dis.readUTF();
} catch (IOException e) {
return "";
} finally {
try { dis.close(); } catch (IOException ignored) {}
try { bais.close(); } catch (IOException ignored) {}
}
}
}
import javax.microedition.rms.*;
public class SimpleRmsStore {
private static final String RECORD_STORE_NAME = "UserConfig";
private RecordStore rms;
/** 讀取記錄 (單記錄模式) */
public String read() {
try {
rms = RecordStore.openRecordStore(RECORD_STORE_NAME, true,
RecordStore.AUTHMODE_ANY, true);
int count = rms.getNumRecords();
if (count == 0) return "";
// 僅讀取第一條記錄 (ID=1)
return RmsCodec.toString(rms.getRecord(1));
} catch (Exception e) {
return "";
} finally {
closeQuietly();
}
}
/** 保存記錄 (覆蓋模式:無則創建,有則更新) */
public String save(String data) {
try {
rms = RecordStore.openRecordStore(RECORD_STORE_NAME, true,
RecordStore.AUTHMODE_ANY, true);
byte[] bytes = RmsCodec.toBytes(data);
if (rms.getNumRecords() == 0) {
rms.addRecord(bytes, 0, bytes.length); // 創建第一條
} else {
rms.setRecord(1, bytes, 0, bytes.length); // 更新第一條
}
return "保存成功";
} catch (Exception e) {
return "保存失敗: " + e.getMessage();
} finally {
closeQuietly();
}
}
/** 刪除記錄存儲 (重置) */
public void clear() {
try {
RecordStore.deleteRecordStore(RECORD_STORE_NAME);
} catch (Exception ignored) {}
}
private void closeQuietly() {
if (rms != null) {
try { rms.closeRecordStore(); } catch (Exception ignored) {}
rms = null;
}
}
}
public class ListRmsStore {
private static final String STORE_NAME = "GameScores";
private RecordStore rms;
/** 保存分數列表 (每條記錄一個分數對象) */
public void saveScores(Vector scores) { // Vector
try {
rms = RecordStore.openRecordStore(STORE_NAME, true,
RecordStore.AUTHMODE_ANY, true);
// 清空舊數據
int[] ids = rms.getRecordIds();
for (int id : ids) rms.deleteRecord(id);
// 寫入新數據
for (int i = 0; i < scores.size(); i++) {
Score s = (Score) scores.elementAt(i);
// 序列化: name#level#score#date
String line = s.name + "#" + s.level + "#" + s.score + "#" + s.date;
rms.addRecord(RmsCodec.toBytes(line), 0, line.length());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeQuietly();
}
}
/** 讀取分數列表 */
public Vector loadScores() {
Vector result = new Vector();
try {
rms = RecordStore.openRecordStore(STORE_NAME, true,
RecordStore.AUTHMODE_ANY, true);
RecordEnumeration enum = rms.enumerateRecords(null, null, false);
while (enum.hasNextElement()) {
int id = enum.nextRecordId();
byte[] data = rms.getRecord(id);
String line = RmsCodec.toString(data);
// 解析: name#level#score#date
String[] parts = split(line, '#');
if (parts.length == 4) {
Score s = new Score();
s.name = parts[0];
s.level = Integer.parseInt(parts[1]);
s.score = Integer.parseInt(parts[2]);
s.date = parts[3];
result.addElement(s);
}
}
enum.destroy();
} catch (Exception e) {
e.printStackTrace();
} finally {
closeQuietly();
}
return result;
}
// split 輔助方法省略...
}
| 場景 | 錯誤做法 | 正確做法 | 理由 |
|---|---|---|---|
| 中文存儲 | str.getBytes() | DataOutputStream.writeUTF() | Modified UTF-8 跨平台安全 |
| 異常處理 | 忽略 close() | finally 塊中 closeQuietly() | 防止 RecordStore 鎖死/句柄洩漏 |
| 頻繁讀寫 | 每次 open/close | 緩存 RecordStore 引用,批量操作 | 減少閃存擦寫,提升性能 |
| 大數據存儲 | 單條記錄存大對象 | 分塊存儲 + 索引記錄 | 單條記錄限制 ~64KB,分塊突破 |
| 數據遷移 | 直接修改格式 | 版本號機制 + 兼容舊格式讀取 | 支持舊版本數據平滑升級 |