首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

J2ME 遊戲開發:使用 RMS (Record Management System) 儲存與讀取最高分紀錄

     編輯:Java 相關知識

RMS (Record Management System) 是 J2ME (MIDP) 提供的持久化儲存機制,類似輕量級資料庫。每個 MIDlet 套件 (JAR) 擁有獨立命名空間的記錄存儲 (RecordStore),每筆記錄包含 recordId (int) 與 data (byte[]) 兩欄。本文詳細說明 RMS 核心 API、操作流程與遊戲最高分儲存實戰。

一、RMS 核心架構

  • RecordStore:對應一張資料表,由名稱識別,屬於特定 MIDlet 套件
  • Record:單筆記錄,兩欄結構:
    • recordId (int):自動遞增主鍵,從 1 開始
    • data (byte[]):任意二進位資料,開發者自行序列化/反序列化

二、RecordStore 核心 API 速查

方法說明
openRecordStore(name, createIfNecessary)開啟/建立記錄存儲,傳回 RecordStore 實例
getNumRecords()取得記錄筆數
getRecordSize(recordId)取得指定記錄資料大小 (bytes)
getRecord(recordId, buffer, offset)讀取記錄到位元組陣列,傳回實際讀取長度
getRecord(recordId)直接傳回記錄資料位元組陣列 (較簡便)
addRecord(data, offset, numBytes)新增記錄,傳回新 recordId
setRecord(recordId, data, offset, numBytes)更新指定記錄
deleteRecord(recordId)刪除單筆記錄
deleteRecordStore(name)刪除整個記錄存儲 (靜態方法)
closeRecordStore()關閉記錄存儲,釋放資源

三、標準操作流程

RecordStore rs = null;
try {
    // 1. 開啟或建立 (true=不存在則建立)
    rs = RecordStore.openRecordStore("HighScores", true);
    
    // 2. 讀寫操作...
    
} catch (Exception e) {
    // 錯誤處理
} finally {
    // 3. 一定要關閉
    if (rs != null) {
        try { rs.closeRecordStore(); } catch (Exception ignore) {}
    }
}

四、資料序列化:int/long/String ↔ byte[]

RMS 僅儲存 byte[],基本型別需手動轉換:

寫入 int 分數


// 寫入單一 int 分數
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeInt(score); // 高位在前
dos.flush();
byte[] data = baos.toByteArray();
rs.addRecord(data, 0, data.length);

讀取 int 分數


byte[] data = rs.getRecord(recordId);
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
int score = dis.readInt();

儲存多筆最高分 (Top 10)


// 讀取所有記錄,反序列化為 int 陣列排序
Vector scores = new Vector();
for (int i = 1; i <= rs.getNumRecords(); i++) {
    byte[] data = rs.getRecord(i);
    scores.addElement(new Integer(readInt(data)));
}
// 排序、截取 Top 10、重寫整個 RecordStore
// (刪除舊存儲重建或逐筆 setRecord)

五、完整遊戲最高分儲存範例


import javax.microedition.rms.*;
import java.io.*;

public class HighScoreManager {
    private static final String STORE_NAME = "GameHighScores";
    private static final int MAX_RECORDS = 10;
    
    // 儲存新分數,自動維護 Top 10
    public static void saveScore(int newScore) {
        RecordStore rs = null;
        try {
            rs = RecordStore.openRecordStore(STORE_NAME, true);
            
            // 讀取現有分數
            Vector scores = new Vector();
            for (int i = 1; i <= rs.getNumRecords(); i++) {
                scores.addElement(new Integer(readInt(rs.getRecord(i))));
            }
            
            // 插入新分數並排序 (降冪)
            scores.addElement(new Integer(newScore));
            // 簡易排序...
            // 只保留前 10
            while (scores.size() > MAX_RECORDS) {
                scores.removeElementAt(scores.size() - 1);
            }
            
            // 重寫存儲:刪除舊記錄、重新寫入
            // 策略:刪除整個存儲重建 (最簡單)
            rs.closeRecordStore();
            RecordStore.deleteRecordStore(STORE_NAME);
            rs = RecordStore.openRecordStore(STORE_NAME, true);
            
            for (int i = 0; i < scores.size(); i++) {
                int score = ((Integer)scores.elementAt(i)).intValue();
                rs.addRecord(toByteArray(score), 0, 4);
            }
            
        } catch (Exception e) {
            // 記錄錯誤
        } finally {
            closeQuietly(rs);
        }
    }
    
    // 取得最高分陣列
    public static int[] getTopScores() {
        RecordStore rs = null;
        Vector scores = new Vector();
        try {
            rs = RecordStore.openRecordStore(STORE_NAME, false); // 不建立
            if (rs != null) {
                for (int i = 1; i <= rs.getNumRecords(); i++) {
                    scores.addElement(new Integer(readInt(rs.getRecord(i))));
                }
            }
        } catch (Exception e) {
        } finally {
            closeQuietly(rs);
        }
        int[] result = new int[scores.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = ((Integer)scores.elementAt(i)).intValue();
        }
        return result;
    }
    
    // 工具方法
    private static byte[] toByteArray(int value) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeInt(value);
        return baos.toByteArray();
    }
    private static int readInt(byte[] data) throws IOException {
        DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
        return dis.readInt();
    }
    private static void closeQuietly(RecordStore rs) {
        if (rs != null) try { rs.closeRecordStore(); } catch (Exception ignore) {}
    }
}

六、關鍵注意事項

  • 同步存取:RMS 非執行緒安全,多執行緒讀寫需自行同步
  • 空間限制:手機 RMS 空間有限 (通常 100KB~1MB),避免儲存大量資料
  • 記錄 ID 不重用:刪除記錄後 ID 不會重複使用,getNumRecords() 可能小於最大 ID
  • 異常處理:所有操作拋 RecordStoreException、RecordStoreFullException、RecordStoreNotFoundException,必須捕獲
  • 版本相容:資料格式變更需自行處理遷移,RMS 無 Schema 概念

七、結語

RMS 是 J2ME 遊戲持久化儲存的標準方案。掌握 RecordStore 生命週期管理、位元組陣列序列化、記錄增刪改查核心流程,即可實作最高分、遊戲進度、設定檔等儲存需求。注意資源釋放與異常處理,確保在受限裝置上穩定運行。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved