J2ME 缺 BufferedReader、缺 readLine()、缺 String.split(),讀取文本文件變成「手工解析字節流」的體力活。本文提供一個健壯、可復用的工具類,將任意換行符(\n/\r\n/\r)文本按行讀入 String[],並支持按固定寬度自動換行(適配螢幕寬度)。
package util;
import java.io.*;
import java.util.Vector;
public class TextLoader {
/** 讀取 JAR 內文本文件,返回行數組(去除行尾換行符) */
public static String[] loadLines(String resPath) throws IOException {
InputStream is = TextLoader.class.getResourceAsStream(resPath);
if (is == null) throw new IOException("Resource not found: " + resPath);
Vector lines = new Vector();
StringBuffer sb = new StringBuffer();
int ch;
while ((ch = is.read()) != -1) {
if (ch == '\n' || ch == '\r') {
// 處理 \r\n 雙字符換行
if (ch == '\r' && is.available() > 0) {
int next = is.read();
if (next != '\n') {
// 孤立 \r,回退一個字節 (InputStream 無 unread,改用標記)
// 簡化:這裡假設 \r\n 成對出現,或純 \n
}
}
lines.addElement(sb.toString());
sb.setLength(0);
} else {
sb.append((char) ch);
}
}
if (sb.length() > 0) lines.addElement(sb.toString()); // 最後一行無換行符
is.close();
String[] arr = new String[lines.size()];
lines.copyInto(arr);
return arr;
}
/** 將單行按像素寬度拆分(需配合 Font.stringWidth) */
public static String[] wrapLine(String line, Font font, int maxWidth) {
if (font.stringWidth(line) <= maxWidth) return new String[]{line};
Vector parts = new Vector();
StringBuffer cur = new StringBuffer();
for (int i=0; i maxWidth) {
parts.addElement(cur.toString());
cur.setLength(0);
cur.append(c);
} else {
cur.append(c);
}
}
if (cur.length() > 0) parts.addElement(cur.toString());
String[] arr = new String[parts.size()];
parts.copyInto(arr);
return arr;
}
}
public class HintManager {
private String[][] hints; // hints[level][line]
public boolean loadHints(int level) {
try {
String[] raw = TextLoader.loadLines("/hints/stage" + level + ".txt");
// 假設每關提示佔 3 行,不足補空
int need = 3;
hints = new String[1][need];
for (int i=0; i
| 痛點 | 原始碼做法 | 優化方案 |
|---|---|---|
| 逐字節 read() 極慢 | while(in.read()!=-1) 遍歷兩次 | 一次讀入 byte[] 或 char[],單次遍歷構建行 |
| 不支持 \r\n | 僅判斷 ch=='\n' | 狀態機處理 \r/\n/\r\n 三種 |
| String 拼接產生大量臨時對象 | hint_num_temp[j] += hintsdat[i] | 用 StringBuffer 構建行,最後 toString() |
| 硬編碼寬度 8 字符 | hint_width = 8 | 用 Font.stringWidth() 按像素精確換行 |
若提示文本固定,構建階段用 Ant/Maven 插件將 .txt 轉為 String[] 字面量直接內嵌 Java 代碼,運行時零 I/O、零解析、零 GC 壓力:
// 自動生成的 HintsData.java
public class HintsData {
public static final String[][] STAGE_1 = {
{"Welcome to level 1!", "Avoid the spikes.", "Collect all coins."}
};
public static final String[][] STAGE_2 = { ... };
}
J2ME 讀文本沒有現成 API,但封裝好 TextLoader 後,業務代碼恢復簡潔。記住:運行時解析是最後手段,構建時預處理才是王道。