JSR 75 定義了兩個可選包:PIM (個人信息管理) 和 FC (FileConnection)。FC API 讓 MIDlet 能夠訪問設備本地文件系統 (內存卡、手機內存),讀寫大文件、與其他應用共享數據、支持用戶導入導出,徹底解決 RMS 體積小、無文件系統交互的痛點。
| 維度 | RMS | FileConnection (FC) |
| 存儲容量 | ~100KB-1MB | 受限於存儲卡/閃存 (MB-GB) |
| 數據結構 | 記錄集 (byte[]) | 完整文件系統 (目錄/文件) |
| 跨應用共享 | 不支持 (AUTHMODE_ANY 僅同套件) | 原生支持 (文件級共享) |
| 文件操作 | 無 | 創建/刪除/重命名/列表/屬性 |
| 強制實現 | 是 (MIDP 1.0+) | 可選 (需設備支持 JSR 75) |
| 安全模型 | 套件隔離 | 簽名域 + 用戶授權提示 |
核心類與接口
- javax.microedition.io.file.FileConnection:核心接口,繼承
StreamConnection,提供文件/目錄操作
- javax.microedition.io.file.FileSystemRegistry:管理根目錄枚舉、監聽器註冊
- javax.microedition.io.file.FileSystemListener:監聽文件系統變化 (插拔卡、文件增刪改)
- 異常:
IllegalModeException (模式錯誤)、ConnectionClosedException (操作已關閉連接)
設備支持檢測
String version = System.getProperty("microedition.io.file.FileConnection.version");
if (version != null) {
// 支持 JSR 75 FC API,版本通常為 "1.0"
} else {
// 不支持,降級使用 RMS
}
// 注意:摩托羅拉早期設備使用 com.motorola.io.file 包,API 幾乎相同
文件讀寫完整實戰
1. 打開文件 (三種模式)
FileConnection fconn = null;
try {
// READ / READ_WRITE / WRITE
fconn = (FileConnection) Connector.open("file:///a/mobile/audio/playlist.txt", Connector.READ_WRITE);
// 關鍵:open() 不拋異常即使文件不存在,必須調用 exists() 判斷
if (!fconn.exists()) {
fconn.create(); // 創建文件
}
} catch (IOException e) { /* 處理 */ }
2. 讀取文件 (DataInputStream 模式)
private void loadPlaylist() {
FileConnection fconn = null;
DataInputStream dis = null;
try {
fconn = (FileConnection) Connector.open("file:///a/mobile/audio/playlist.txt", Connector.READ);
if (!fconn.exists()) return;
dis = fconn.openDataInputStream();
musicList.removeAllElements();
String path;
while ((path = dis.readUTF()) != null) { // 協議:路徑、名稱、大小
String name = dis.readUTF();
long size = dis.readLong();
MusicInfo info = new MusicInfo(path, name, size);
musicList.addElement(info);
}
} catch (EOFException e) {
// 正常讀取結束
} catch (IOException e) {
e.printStackTrace();
} finally {
try { if (dis != null) dis.close(); } catch (IOException ignored) {}
try { if (fconn != null) fconn.close(); } catch (IOException ignored) {}
}
}
3. 寫入文件 (DataOutputStream + 原子替換)
private void savePlaylist() {
FileConnection fconn = null;
DataOutputStream dos = null;
try {
fconn = (FileConnection) Connector.open("file:///a/mobile/audio/playlist.txt", Connector.READ_WRITE);
// 原子替換策略:刪除舊文件 → 創建新文件 → 寫入
if (fconn.exists()) fconn.delete();
fconn.create();
dos = fconn.openDataOutputStream();
for (int i = 0; i < musicList.size(); i++) {
MusicInfo info = (MusicInfo) musicList.elementAt(i);
dos.writeUTF(info.path);
dos.writeUTF(info.name);
dos.writeLong(info.size);
}
dos.flush(); // 強制刷新到存儲介質
} catch (IOException e) {
e.printStackTrace();
} finally {
try { if (dos != null) dos.close(); } catch (IOException ignored) {}
try { if (fconn != null) fconn.close(); } catch (IOException ignored) {}
}
}
目錄操作與枚舉
// 判斷是否目錄
boolean isDir = fconn.isDirectory();
// 創建目錄 (需完整路徑)
FileConnection dir = (FileConnection) Connector.open("file:///a/mobile/myfolder", Connector.READ_WRITE);
dir.mkdir();
// 列舉目錄內容
Enumeration enum = fconn.list(); // 返回 String 枚舉 (文件名/目錄名)
while (enum.hasMoreElements()) {
String name = (String) enum.nextElement();
// 處理 name...
}
// 也可強制轉型:String[] list = (String[]) fconn.list(); (實現細節依賴設備)
文件系統監聽器:響應 SD 卡插拔
public class StorageListener implements FileSystemListener {
public void stateChanged(int state, String rootName) {
switch (state) {
case FileSystemListener.ROOT_ADDED:
// SD 卡插入,rootName 如 "file:///b/"
scanNewStorage(rootName);
break;
case FileSystemListener.ROOT_REMOVED:
// SD 卡拔出
invalidateStorage(rootName);
break;
}
}
}
// 註冊監聽
FileSystemRegistry.addFileSystemListener(new StorageListener());
安全模型與簽名現實
| 簽名狀態 | 讀取權限 | 寫入權限 | 用戶提示 |
| 未簽名/自簽名 | 每次提示允許 | 禁止 | 極其頻繁,體驗極差 |
| 運營商簽名 | 允許 (可配置) | 允許 (可配置) | 首次/會話提示 |
| 廠商/根簽名 | 靜默允許 | 靜默允許 | 無提示 |
現實建議:涉及 FC API 的商業應用,**必須申請運營商/廠商簽名**,否則用戶體驗不可接受。
最佳實踐總結
- 路徑規範:使用
FileSystemRegistry.listRoots() 獲取根目錄,拼接相對路徑,避免硬編碼
- 異常安全:所有流/連接在
finally 中關閉
- 原子寫入:臨時文件寫入完成 → 重命名覆蓋,防止寫入中斷損壞數據
- 大文件分塊:大文件讀寫分塊處理,避免 OOM
- 編碼統一:文本文件統一 UTF-8,二進制文件自定義協議
FC API 讓 J2ME 具備了真正的文件級數據管理能力,是豐富應用功能的關鍵擴展。
- 上一篇文章: J2ME 2D 繪圖坐標系統變換:translate 平移與滾動背景實現
- 下一篇文章: Java 藍牙無線通信技術 API 概述 (JSR 82)
Copyright ©
程式碼之家 All Rights Reserved