openFileOutput() 是 Context 方法,非 Activity 類中無法直接調用。
// 工具類
public class FileUtils {
public static void writeToFile(Context context, String filename, String content) {
FileOutputStream fos = null;
try {
// 關鍵:context.openFileOutput()
fos = context.openFileOutput(filename, Context.MODE_PRIVATE);
fos.write(content.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
Log.e("FileUtils", "Write failed", e);
} finally {
if (fos != null) {
try { fos.close(); } catch (IOException ignored) {}
}
}
}
public static String readFromFile(Context context, String filename) {
StringBuilder sb = new StringBuilder();
try (FileInputStream fis = context.openFileInput(filename);
InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append('\n');
}
} catch (IOException e) {
Log.e("FileUtils", "Read failed", e);
}
return sb.toString();
}
}
// Activity 中
FileUtils.writeToFile(this, "myFile.txt", "Hello World");
// Fragment 中
FileUtils.writeToFile(requireContext(), "myFile.txt", "Hello World");
// Service / BroadcastReceiver 等任何 Context 子類
FileUtils.writeToFile(getApplicationContext(), "myFile.txt", "Hello World");
// FileUtils.kt
fun Context.writeInternalFile(filename: String, content: String) {
openFileOutput(filename, MODE_PRIVATE).use { it.write(content.toByteArray()) }
}
fun Context.readInternalFile(filename: String): String {
return openFileInput(filename).bufferedReader().use { it.readText() }
}
// 使用極其簡潔
this.writeInternalFile("config.json", jsonString)
val json = this.readInternalFile("config.json")
Context.openFileOutput() 創建的文件私有於該應用,路徑 /data/data/pkg/files/ApplicationContext 更安全 (生命周期最長)BufferedOutputStream、MappedByteBuffer、或遷移至 Room/DataStore
// Preferences DataStore (鍵值對)
val Context.dataStore: DataStore by preferencesDataStore(name = "settings")
// 寫入
suspend fun Context.saveToken(token: String) {
dataStore.edit { it.putString("token", token) }
}
// 讀取 (Flow)
val tokenFlow: Flow = context.dataStore.data
.map { prefs -> prefs.getString("token") ?: "" }
優點:異步、事務性、遷移自動、協程整合、主線程安全。