RMS 只能存鍵值對,無法訪問真實文件系統。JSR 75 (PDA Optional Packages) 引入 FileConnection API (FC API),提供標準 javax.microedition.io.file 包,支持文件/目錄增刪改查、輸入輸出流、文件系統監聽。本文系統講解 FC API 核心類、讀寫代碼模式、目錄操作、監聽器與安全機制。
| 特性 | RMS | FileConnection API |
|---|---|---|
| 數據模型 | 記錄存儲 (Record Store) | 真實文件系統 (文件/目錄樹) |
| 跨應用共享 | 不可共享 (私有) | 可讀取/寫入其他應用文件、SD 卡 |
| 存儲上限 | 通常 < 100KB~1MB | 受限於文件系統剩餘空間 (MB~GB) |
| 適用場景 | 配置、高分、遊戲存檔 | 音樂播放列表、大地圖數據、日誌、用戶導入導出 |
| 強制實現 | 所有 MIDP 設備必須 | 可選包,僅部分手機支持 (Moto A 系列、部分麼 S60、WM 手機) |
FileConnection (extends StreamConnection):文件/目錄操作句柄,提供 openInputStream()/openOutputStream()/openDataInputStream()/openDataOutputStream()、mkdir()/delete()/list()/exists()/isDirectory() 等。FileSystemRegistry:listRoots() 獲取所有根目錄 (如 file:///a/、file:///b/),addFileSystemListener() 註冊監聽器。FileSystemListener:stateChanged(int state, String rootName),狀態碼:ROOT_ADDED (插入 SD)、ROOT_REMOVED (拔出 SD)。IllegalModeException (只讀寫入)、ConnectionClosedException (操作已關閉連接)。String ver = System.getProperty("microedition.io.file.FileConnection.version");
if (ver != null) { /* 支持,版本通常 "1.0" */ }
else { /* 不支持,降級用 RMS */ }
private void loadPlaylist() {
FileConnection fc = null; DataInputStream dis = null;
try {
fc = (FileConnection) Connector.open(
"file:///a/mobile/audio/playlist.txt", Connector.READ);
if (!fc.exists()) return; // 關鍵:文件不存在不拋異常,必須自查
dis = fc.openDataInputStream();
String path;
while ((path = dis.readUTF()) != null) {
String name = dis.readUTF();
long size = dis.readLong();
playlist.add(new Track(path, name, size));
}
} catch (EOFException e) { /* 正常讀完 */ }
catch (Exception e) { e.printStackTrace(); }
finally { close(dis); close(fc); }
}
private void savePlaylist() {
FileConnection fc = null; DataOutputStream dos = null;
try {
fc = (FileConnection) Connector.open(
"file:///a/mobile/audio/playlist.txt", Connector.READ_WRITE);
if (!fc.exists()) fc.create(); // 創建文件
else { fc.delete(); fc.create(); } // 簡單覆蓋策略
dos = fc.openDataOutputStream();
for (Track t : playlist) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream td = new DataOutputStream(bos);
td.writeUTF(t.path); td.writeUTF(t.name); td.writeLong(t.size);
td.close();
dos.write(bos.toByteArray());
bos.close();
}
dos.flush();
} catch (Exception e) { e.printStackTrace(); }
finally { close(dos); close(fc); }
}
// 創建目錄
FileConnection fc = (FileConnection) Connector.open(
"file:///a/mobile/music", Connector.READ_WRITE);
fc.mkdir();
// 列舉目錄內容
Enumeration en = fc.list(); // 返回 String 枚舉 (文件/目錄名)
while (en.hasMoreElements()) {
String name = (String) en.nextElement();
// 判斷是文件還目錄需再 open 該子項調用 isDirectory()
}
public class SDListener implements FileSystemListener {
public void stateChanged(int state, String rootName) {
if (state == FileSystemListener.ROOT_ADDED) {
// SD 卡插入,掃描新媒體文件
} else if (state == FileSystemListener.ROOT_REMOVED) {
// SD 卡拔出,清理引用、暫停播放
}
}
}
// 註冊
FileSystemRegistry.addFileSystemListener(new SDListener());
SecurityException)。com.motorola.io.file) 甚至完全封殺未簽名應用讀取。結論:涉及 FC API 的產品級應用,**務必申請廠商/運營商簽名**,否則幾乎不可用。