Androidのファイル入出力で結構悩んだのでそのメモ。
Androidでは、誰でも好きなパスに書き込みができるわけではありません!アプリの権限の許された部分のみに書き込みできます。書き込みができるのは、次のディレクトリです。
可能なパス | 補足 |
|---|---|
/sdcard/xxx | SDカード |
/data/data/パッケージ名/xxx | データフォルダ |
ニアミスとして、test というファイルを書こうと頑張っていて、なぜか書けない・・・なぜだ~と悩んでいたら、test というフォルダが既にあったんです。間違っていたのは、以下のようなコード。
File f = new File("/sdcard/hoge/test.txt");
f.mkdirs(); // ←ここが間違い
// フォルダなので当然エラー!!
FileOutputStream fo = new FileOutputStream(f);
この時に、f.canWrite() で調べても、true が返ってくるので、なぜだ?!と思っていたのですが、ぼーっとしていて、フォルダとファイルの区別がついていなかったというオチ。
Androidのリソースとしてファイルを埋め込んだ場合、つまり、assets ディレクトリの場合。単純に /android_assets/xxx のようなパスを書いてもファイルを取り出せません。AssetManager を使ってファイルをオープンする必要があります。以下、アセットからSDカードにファイルをコピーするメソッド。
private static int BUFFSIZE = 1024 * 16;
public static boolean copyAssetsFile(Activity app, String assetsName, String savepath) {
FileOutputStream fo;
InputStream inp;
try {
File f = new File(savepath);
File parent = f.getParentFile();
if (parent != null && parent.canWrite()) { parent.mkdirs(); }
fo = new FileOutputStream(f);
} catch (IOException e) {
Log.e("myapp", "copyAssetsFile() savepath could not open:" + e.getMessage() + ",file=" + savepath);
return false;
}
AssetManager am = app.getResources().getAssets();
try {
byte[] buf = new byte[BUFFSIZE];
inp = am.open(assetsName);
while (true) {
int sz = inp.read(buf, 0, BUFFSIZE);
if (sz <= 0) break;
fo.write(buf, 0, sz);
}
fo.close();
return true;
}catch(IOException e) {
Log.e("myapp", e.getMessage());
return false;
}
}
後は、単純にパスを書き間違えていたとか、そんな感じです。