在 Android 開發中,存取 SD 卡(外部儲存裝置)是常見需求。雖然底層 Java IO API 與標準 Java 無異,但 Android 的權限機制與儲存路徑解析有其特殊規則。本文整理完整流程,並提供兩種路徑取得方式與可直接執行的寫入範例。
Android 6.0 (API 23) 以上需動態申請,但清單檔仍必須宣告:
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Android 10+ 讀取媒體檔案另需 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
注意:Android 10 (API 29) 引入分區儲存,建議改用 MediaStore 或 getExternalFilesDir() 以相容新版政策。
// 早期裝置常見掛載點,新版裝置可能不存在或無權存取
final String FILE_NAME = "/mnt/sdcard/00000.H264";
缺點:裝置碎片化嚴重,路徑可能為 /storage/emulated/0、/sdcard 等,極易失效。
// 取得主要外部儲存目錄(通常指 /storage/emulated/0)
File sdDir = Environment.getExternalStorageDirectory();
String filePath = sdDir.getCanonicalPath() + "/your_file_name.txt";
優點:跨裝置相容、自動處理多使用者/工作資料夾隔離。
public class FileTestActivity extends AppCompatActivity {
private static final String FILE_NAME = "app_data.txt";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnWrite = findViewById(R.id.btn_write);
btnWrite.setOnClickListener(v -> writeToSdCard());
}
private void writeToSdCard() {
// 1. 確認儲存狀態可寫
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
Toast.makeText(this, "SD 卡不可用", Toast.LENGTH_SHORT).show();
return;
}
// 2. 取得檔案物件(建議使用 getExternalFilesDir() 避免權限問題)
File file = new File(getExternalFilesDir(null), FILE_NAME);
// 若需對其他 App 可見,改用 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS)
// 3. 使用 try-with-resources 自動關閉資源 (Java 7+)
try (FileOutputStream fos = new FileOutputStream(file, true); // true = 附加模式
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
String content = "寫入時間:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date()) + "\n";
bos.write(content.getBytes(StandardCharsets.UTF_8));
bos.flush();
Toast.makeText(this, "寫入成功:" + file.getAbsolutePath(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "寫入失敗:" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
}
getBytes(StandardCharsets.UTF_8) 避免中文亂碼。BufferedOutputStream 大幅提升大量寫入效能。new FileOutputStream(file, true) 實現追加寫入而非覆蓋。MediaStore 插入媒體檔案,或 getExternalFilesDir() 存放私有資料(免權限、隨 App 解除安裝自動刪除)。Android 讀寫 SD 卡核心在於:正確聲明權限 → 動態取得標準路徑 → 善用緩衝流與資源自動管理 → 適配分區儲存新政。掌握這套流程,即可穩健處理各類檔案存取需求。