- 2014/06/23 【Android】【Java】SDカードにテキストファイルを保存する
- 2014/06/22 【Android】【Java】SDカードからテキストファイルを読み込む
- 2014/02/26 【Android】エミュレータでSDカードをマウントして使う方法 その2
« prev next »
【Android】【Java】SDカードにテキストファイルを保存する 
2014/06/23 Mon [edit]
保存もついでなので簡単なものを書いて置く。前回の「SDカードからテキストファイルを読み込む」のテスト用に使っても良いだろう。エミュレータ起動中なら DDMS を使っても確認することもできる。
考え方は、「内部ストレージにテキストファイルを保存する」とほぼ変わらない。
saveText() は以前定義したものをそのまま使えば良い。
isMountSDCard(), toSDCardAbsolutePath() も前回のものをそのまま使う。
(※) Android4.4(API 19)あたりから内部ストレージの仮想パスに変わった模様
また書き込みの場合は、マニフェストファイル(AndroidManifest.xml) に以下のパーミッションが必要になる。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
//設定値
private static final String DEFAULT_ENCORDING = "UTF-8"; //デフォルトのエンコード
//出力ストリームにてテキストを保存(汎用)
public static final void saveText(OutputStream outputStream, String text, String charsetName)
throws IOException, UnsupportedEncodingException {
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(outputStream);
bos.write(text.getBytes(charsetName)); //すべての byte[] を取得
bos.flush();
} finally {
try {
bos.close();
} catch (Exception e) {
//IOException
}
}
}
// SDCard のマウント状態をチェックする(Android 用)
public static final boolean isMountSDCard() {
final String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
return true; //マウントされている
} else {
return false; //マウントされていない
}
}
// SDCard のルートディレクトリを取得(Android 用)
public static final File getSDCardDir() {
return Environment.getExternalStorageDirectory();
}
// SDCard 内の絶対パスに変換(Android 用)
public static final String toSDCardAbsolutePath(String fileName) {
return getSDCardDir().getAbsolutePath() + File.separator + fileName;
}
//SDCard に、テキストファイルを保存する
//<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> が必要。
public static final void saveTextSDCard(String fileName, String text) throws IOException {
if (!isMountSDCard()) {
throw new IOException("No Mount");
}
OutputStream os = new FileOutputStream(toSDCardAbsolutePath(fileName));
saveText(os, text, DEFAULT_ENCORDING);
}
//メインでは... (※例外処理は省略)
String fileName = "sample.txt"; // "mnt/sdcard/sample.txt" or "sdcard/sample.txt" 等に保存される(端末による)
String text = "保存する文字列";
saveTextSDCard(fileName, text);
//ファイルが保存されていれば成功(エミュレータならDDMSで確認できる)
文字エンコーディングは読み込みに合わせて "UTF-8" にした方が良いだろう。他のものにしたいなら、ストリームに渡す前に変更してやれば良い。
実機での確認は、「マイファイル」のようなアプリで簡単に覗くことができる(アプリは端末による)。
前回流用の isMountSDCard() では、SDカードのマウント状態だけしかチェックしてないので、必要なら MOUNTED_READ_ONLY (読み取り専用) などもチェックした方が良いかも知れない。その辺は外部ストレージの状態を参考にして、色々付け加えると良いだろう。マウントはあくまで最低限の条件である。
テキストファイルの読み込みや保存をまとめたページは→こちら
(関連記事)
【Android】SDカードからテキストファイルを読み込む
【Android】エラーをSDカードに書き出す
【Android】SDカードから画像ファイルを読み込む
【Android】SDカードに画像ファイルを保存する(png)
【Android】SDカードに画像ファイルを保存する(jpg)
【Android】SDカードのファイルを削除する
【Android】内部ストレージにテキストファイルを保存する
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ
【Android】Preference 機能を使ってデータを読み込み・保存する
【Android】【Java】SDカードからテキストファイルを読み込む 
2014/06/22 Sun [edit]
今度は Android の外部ストレージ(SDカード)からテキストファイルを読み込んでみる。エミュレータで試したいときはSDカードのマウントが必要なので、以下のHPあたり参考にすると良いだろう。上手く行かなければコマンドラインで起動する手もある。
(参考) Androidエミュレーターの仮想SDカードを使う
(参考) SDカードをマウントしてエミュレーターを起動
上手くマウントできたなら、DDMS でも確認できる。マウントフォルダは Android端末によって異なるが、「/sdcard」や「/mnt/sdcard」辺りを覗いて見ればわかるだろう。もしファイルがあれば、DDMS の右上あたりにある [push]ボタンでファイル転送、[pull] ボタンで開発環境にファイルをコピーもできる。
コードは今までよりも少し多くなる。と言っても基本は変わらないのだが、SDカードは脱着が容易なため、常にマウントの状態を確認しなければならない。それと先ほど述べたように、端末によってルートディレクトリが違うので、動的に取得する必要がある。その辺のコードが少し加わっただけだ。
ストリームからのテキストファイル読み込みは例によって以前作ったものをそのまま使う。
loadText() - ストリームからテキストファイルを読み込む
手順を簡単に説明すると、次のようになる。
1.SDカードのマウント状態やルートディレクトリを調べる。
2.SDカードの入力ストリームを開く。
3.ストリームからテキストエンコーディングして文字列を返す。
●SDカードの入力ストリームを開く部分 [Android 用]
(※) Android4.4(API 19)あたりから内部ストレージの仮想パスに変わった模様
//設定値
private static final String DEFAULT_ENCORDING = "UTF-8"; //デフォルトのエンコード
// SDCard のマウント状態をチェックする(Android 用)
public static final boolean isMountSDCard() {
final String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
return true; //マウントされている
} else {
return false; //マウントされていない
}
}
// SDCard のルートディレクトリを取得(Android 用)
public static final File getSDCardDir() {
return Environment.getExternalStorageDirectory();
}
// SDCard 内の絶対パスに変換(Android 用)
public static final String toSDCardAbsolutePath(String fileName) {
return getSDCardDir().getAbsolutePath() + File.separator + fileName;
}
// SDCard から、テキストファイルを読み込む(Android 用)
public static final String loadTextSDCard(String fileName) throws IOException {
if (!isMountSDCard()) { //マウント状態のチェック
throw new IOException("No Mount");
}
InputStream is = new FileInputStream(toSDCardAbsolutePath(fileName));
return loadText(is, DEFAULT_ENCORDING);
}
//メインでは... (※例外処理は省略)
String fileName = "sample.txt"; //"mnt/sdcard/sample.txt" or "sdcard/sample.txt" 等になる(端末による)
String text = loadTextSDCard(fileName);
System.out.println(text); //Log.d("tag", text); でも良い
マウント状態のチェックでは IOException() にメッセージを付けてあるが、判別しずらければ、他の Exception に変えたほうが良いかも知れない。本来なら外部ストレージの状態は様々な定数で表現されているのだが、ここではとりあえず、マウントだけをチェックしている。必要があれば、色々チェックしても良いだろう。
●ストリームからテキストエンコーディングして読み込む部分 [汎用](- loadText() ※以前作ったものを使い回し)
//設定値
private static final int DEFAULT_READ_LENGTH = 8192; //一度に読み込むバッファサイズ
//ストリームから読み込み、バイト配列で返す
public static final byte[] readStream(InputStream inputStream, int readLength) throws IOException {
final ByteArrayOutputStream byteStream = new ByteArrayOutputStream(readLength); //一時バッファのように使う
final byte[] bytes = new byte[readLength]; //read() 毎に読み込むバッファ
final BufferedInputStream bis = new BufferedInputStream(inputStream, readLength);
try {
int len = 0;
while ((len = bis.read(bytes, 0, readLength)) > 0) {
byteStream.write(bytes, 0, len); //ストリームバッファに溜め込む
}
return byteStream.toByteArray(); //byte[] に変換
} finally {
try {
byteStream.reset(); //すべてのデータを破棄
bis.close(); //ストリームを閉じる
} catch (Exception e) {
//IOException
}
}
}
//ストリームから読み込み、テキストエンコードして返す
public static final String loadText(InputStream inputStream, String charsetName)
throws IOException, UnsupportedEncodingException {
return new String(readStream(inputStream, DEFAULT_READ_LENGTH), charsetName);
}
次回は SDカードへの書き込みも考えてみよう。と言ってもこれまでのものを組み合わせると簡単にできる。
テキストファイルの読み込みや保存をまとめたページは→こちら
(関連記事)
【Android】SDカードにテキストファイルを保存する
【Android】エラーをSDカードに書き出す
【Android】SDカードから画像ファイルを読み込む
【Android】SDカードのファイルを削除する
【Android】res/raw リソースフォルダからテキストファイルを読み込む
【Android】assets フォルダからテキストファイルを読み込む
【Android】内部ストレージからテキストファイルを読み込む
【Android】内部ストレージにテキストファイルを保存する
【汎用】ストリームからテキストファイルを読み込む(ストリームから読み込み、テキストエンコードして返す)
【汎用】ローカルシステム(Windows 等)から、テキストファイルを読み込む
【Applet/汎用】URL経由でWebサーバ上のテキストファイルを読み込む
【Applet】jar 内リソースからテキストファイルを読み込む
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ
【Android】Preference 機能を使ってデータを読み込み・保存する
【Android】エミュレータでSDカードをマウントして使う方法 その2 
2014/02/26 Wed [edit]
いきなり「その2」なのは、「その1」はググるれば出てくるやり方で、
Androidエミュレーターの仮想SDカードを使う
などの方法。
しかし、なぜか私の開発環境では上手く行かなかった。
理由は定かではないが、Eclipse からでは、どうしてもSDカードがマウントされた状態にならない。よくエミュレータ起動時に adb との接続が切れて、何度か起動失敗するせいかも知れない(PCが古い)。接続タイムアウトを伸ばしたり、adb shell でリマウントしても無理だった。Eclipse のファイルエクスプローラや adb 上は成功するが、エミュレータがSDカードを認識しない。ついでに sdutil もなぜか Not Found になる。環境が古いだけかも知れないが、他に問題は無いし…。
とりあえず、このままの環境(Android2.2以降対応/ADT Build: v22.0.5)で、何か方法はないかな~、とコマンドプロンプトで色々やってみたら、上手くSDカードが使えるようになった。その方法。
1.SDK の tools フォルダから emulator コマンド(exe)を使って直接エミュレータを起動(SDカードのマウントも指定)。
emulator -sdcard sdcard.img -avd [AVD名]
※仮想SDカードのイメージファイル(sdcard.img)は「その1」と同様(mksdcard.exeで作る)。イメージファイルのパス名に空白文字を入れてはならない("Program Files"とか)。
※[AVD名]は仮想デバイス・マネージャーでの登録名(AVD名)
2.起動後、SDK の platform-tools フォルダから adb(exe) とエミュレータを接続し直す。
adb kill-server
adb start-server
adb devices
※「adb devices」でエミュレータがリストに出てくればOK。
3.再接続が成功したら、必要なファイルをSDカードに転送する。
adb push [ファイル名] mnt/sdcard
4.あとは「その1」と同じやり方で「DevTools」から「Media Scanner」でファイルをエミュレータで認識させると、エミュレータの Gallery や Music で使用できる。
プログラムコードからSDカードにファイルを保存する場合は、「AndroidManifest.xml」に、
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
を入れるのを忘れずに。
ただ読み込むだけなら、コンテンツプロバイダの機能を使えば利用できる。その辺はググればいくらでもサンプルが出てくるだろう。
何らかの原因でエミュレータとの接続が切れた場合も、adb の再接続だけで事足りるかも知れない。
(関連記事)
【Android】SDカードからテキストファイルを読み込む
【Android】SDカードにテキストファイルを保存する
【Android】エラーをSDカードに書き出す
【Android】SDカードから画像ファイルを読み込む
【Android】SDカードに画像ファイルを保存する(png)
【Android】SDカードに画像ファイルを保存する(jpg)
【Android】SDカードのファイルを削除する
【AndroidStudio】AndroidStudio 2.x で DDMS を表示する