ヽ|∵|ゝ(Fantom) の 開発blog? ホーム »テキストファイル保存
このページの記事一覧

【Android】【Java】エラーをSDカードに書き出す  


 エミュレータではエラーが出ない(もしくは操作などの関係でテストしにくいなど)のに、実機ではエラーが出るときってあるよね。だけど「エラー:〇〇が予期せず停止しました。」だけだとデバッグするのが難しいので、例外のスタックトレースをそのままSDカードに保存する方法をやってみよう。あくまでも開発者用で特別な機能は何も付いてないので、その辺は自分で自由に付け足して使って欲しい。

●例外(エラー)のスタックトレースをSDカードに書き出すクラス
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import android.os.Environment;

/**<h1>エラーを SDカードに書き出す</h1>
* <p>マニフェストファイルに WRITE_EXTERNAL_STORAGE の属性と、SDカードをあらかじめマウントしておくことが必要。</p>
*/
public class ErrorReporter implements UncaughtExceptionHandler {

//マニフェストファイルに
//<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
//が必要

//※SDカードのルートに保存される。ルートは実機によって「/sdcard」や「/mnt/sdcard」など異なる。
static final File errorReportFile = new File(Environment.getExternalStorageDirectory().getPath()
+ File.separator + "error_report.txt"); //※ファイル名は任意

//コンストラクタ
public ErrorReporter() {
}

//catch されなかった例外を受け取るハンドラ
@Override
public void uncaughtException(Thread thread, Throwable ex) {
PrintWriter pw = null;
try {
//※ここでエラーにならないように注意(要 SD カード[マウント])
pw = new PrintWriter(new FileOutputStream(errorReportFile));
ex.printStackTrace(pw);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
pw.close();
} catch (Exception e2) {
}
pw = null;
}
}
}

 使い方は以下に示す使用例のように Activity のコンストラクタ(または onCreate()) などでハンドラとしてインスタンス化すれば良いだけだ。ボタンなどはテスト用なので任意で良い。終了処理などは何も付けてないので、実際にエラーが発生したときはフリーズしたようになる。なので、アプリは手動で終了して欲しい。

 try~catch~finally ブロックは少し冗長に感じるが、try-with-resources 文は API 19(Android4.4)以降しか使えないようなので、この方が無難だろう。使用中はSDカードが実機に入っていることを前提としている。普通にSDカードが読み書きできている分にはここで例外が発生することは無いハズだ。もちろん、マニフェストファイルに「SDカードへ書き込み許可」を書いておくことも必要となる。例外捕捉中に例外を発生させないよう気をつけよう(笑)。

●SD カードの書き込みを許可するタグ(<manifest>~</manifest>の間が良い)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


●使用例(ボタンを押すとエラーが発生するテスト用)
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

int[] data = new int[3]; //エラーテスト用

public MainActivity() {
//catch されなかった例外を受け取るハンドラを設定
Thread.setDefaultUncaughtExceptionHandler(new ErrorReporter()); //onCreate() でも良い
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main); //ボタン1個のレイアウト(任意)

//わざと例外を発生させるボタン
Button button1 = (Button)this.findViewById(R.id.button1);
button1.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("LOG", "button1 onClick");
data[5] = 1; //ArrayIndexOutOfBoundsException
}
});
}
}

●出力された「error_report.txt」の内容
java.lang.ArrayIndexOutOfBoundsException
at com.example.testandroid.MainActivity$1.onClick(MainActivity.java:28)
at android.view.View.performClick(View.java:2408)
at android.view.View$PerformClick.run(View.java:8816)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)

 実際にメインに必要なコードは「Thread.setDefaultUncaughtExceptionHandler(new ErrorReporter());」の1行だけになる。上の例ではコンストラクタで定義しているが、onCreate() でも構わない。もちろん、エラーが発生する前である必要はある。

 出力されたテキストファイルはSDカードのルートに置かれ(実機によって「/sdcard」や「/mnt/sdcard」など異なる)、スマホに元から入っている「マイファイル」(アプリ名は端末よる)などでそのまま覗ける。エミュレータ上でも「DDMS」で右上にある「pull」ボタンを押せば、ローカルに落とせる。テキストエディタなどで確認すれば良い。なお、ファイル名は任意で良い。


 ちなみに元ネタは「アプリがエラーで強制終了したときに、バグレポートを送信する機能」で、それを超簡単にして、SDカードにエラーを吐き出させる機能のみに限定したものだったりする。なのでユーザー向けでなく、自分用(開発者用)という感じなので、ダイアログすら付けてない。ちゃんとしたものが欲しければ以下のURLを参照して欲しい。メモリ使用状況やビルドのバージョン情報などを付加するのもデバッグの役に立つかも知れない。

(参考)
Androidアプリのバグ報告システムを考える
Android キャッチされなかった例外を処理する
Android でアプリケーションが強制終了したとき、エラーレポートを送るようにする

(SDカードの書き込み権限など)
【スマホのコツ】Android5.0以上でSDカードへ書き込みができるファイラーアプリとその方法


(関連記事)
【Android】エミュレータでSDカードをマウントして使う方法 その2
【Android】SDカードにテキストファイルを保存する
【Android】SDカードからテキストファイルを読み込む
【Android】内部ストレージにテキストファイルを保存する
【Android】Preference 機能を使ってデータを読み込み・保存する
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ


スポンサーサイト

category: Android

thread: プログラミング

janre: コンピュータ

tag: テキストファイル保存  SDカード 
tb: 0   cm: --

【Android】【Java】Preference 機能を使って設定データを読み込み・保存する  


 ついでに、これまでの「テキストファイルの読み込み・書き込み」とは少し違うのだが、Android には設定データなど、「キーと値」のペアで構成された、小さなデータを読み書きできる Preference(プリファレンス)という機能がある。簡単なものなら、この Preference 機能を使った方が、テキストファイルの読み書きよりも簡単にできるので、汎用性は無いが、覚えておいても損はないだろう。同じようなものがいくつかあるので、用途によって使い分けるのが良い。

 簡単な分類や違いは次の通り。

クラス名メソッド名概要保存ファイルパス
ActivitygetPreferences()Activity 固有の設定値を記録する。ファイル名はアクティビティ名固定。/data/data/[パッケージ名]/shared_prefs/[Activity名].xml
ContextgetSharedPreferences()アプリ固有の設定値を記録する。ファイル名は引数で自由に決められる。/data/data/[パッケージ名]/shared_prefs/[引数の名前].xml
PreferenceManagergetDefaultSharedPreferences()アプリ固有の設定値を記録する。ファイル名は固定。
※テンプレートの「SettingsActivity」(PreferenceActivity)等はこれ。
/data/data/[パッケージ名]/shared_prefs/[パッケージ名]_preference.xml

 用途の使い分けは、ちょっとした保存なら、PreferenceManager クラスの getDefaultSharedPreferences() で、細かくファイルを分けて保存したいなら、Context クラスの getSharedPreferences() あたりを使うと良いかも知れない。



■Activity 固有の設定データを読み込む[Activity クラス getPreferences()]
//Activity 固有の設定データを読み込む(Activity クラス)
//ファイルは "/data/data/[パッケージ名]/shared_prefs/[Activity名].xml" になる

SharedPreferences pref = getPreferences(MODE_PRIVATE);
String str = pref.getString("str", "defValue"); //読み込み
int val = pref.getInt("val", -1); //読み込み
System.out.println("str = " + str);
System.out.println("val = " + val);

■Activity 固有の設定データを保存する[Activity クラス getPreferences()]
//Activity 固有の設定データを保存する(Activity クラス)
//ファイルは "/data/data/[パッケージ名]/shared_prefs/[Activity名].xml" になる

SharedPreferences pref = getPreferences(MODE_PRIVATE);
String str = "あいうえお"; //保存値
int val = 100; //保存値
SharedPreferences.Editor editor = pref.edit();
editor.putString("str", str);
editor.putInt("val", val);
editor.commit(); //ここで保存




■アプリ固有の設定データを読み込む[Context クラス getSharedPreferences()]
//アプリ固有の設定データを読み込む(Context クラス)
//ファイルは "/data/data/[パッケージ名]/shared_prefs/[引数の名前].xml" になる

SharedPreferences pref = getSharedPreferences("name", MODE_PRIVATE);
String str = pref.getString("str", "defValue"); //読み込み
int val = pref.getInt("val", -1); //読み込み
System.out.println("str = " + str);
System.out.println("val = " + val);

■アプリ固有の設定データを保存する[Context クラス getSharedPreferences()]
//アプリ固有の設定データを保存する(Context クラス)
//ファイルは "/data/data/[パッケージ名]/shared_prefs/[引数の名前].xml" になる

SharedPreferences pref = getSharedPreferences("name", MODE_PRIVATE);
String str = "あいうえお"; //保存値
int val = 100; //保存値
SharedPreferences.Editor editor = pref.edit();
editor.putString("str", str);
editor.putInt("val", val);
editor.commit(); //ここで保存




■アプリ固有の設定データを読み込む[PreferenceManager クラス getDefaultSharedPreferences()]
//アプリ固有の設定データを読み込む(PreferenceManager クラス)
//ファイルは "/data/data/[パッケージ名]/shared_prefs/[パッケージ名]_preference.xml" になる

SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); //this は Activity 等の Context
String str = pref.getString("str", "defValue"); //読み込み
int val = pref.getInt("val", -1); //読み込み
System.out.println("str = " + str);
System.out.println("val = " + val);

■アプリ固有の設定データを保存する[PreferenceManager クラス getDefaultSharedPreferences()]
//アプリ固有の設定データを保存する(PreferenceManager クラス)
//ファイルは "/data/data/[パッケージ名]/shared_prefs/[パッケージ名]_preference.xml" になる

SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); //this は Activity 等の Context
String str = "あいうえお"; //保存値
int val = 100; //保存値
SharedPreferences.Editor editor = pref.edit();
editor.putString("str", str);
editor.putInt("val", val);
editor.commit(); //ここで保存




 使い方はすべて同じ。中身は xml 形式ではあるが、テキストファイルなので、DDMS を使って [pull] でローカルに落とし、覗くこともできる。

●保存された xml ファイル内容
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="str">あいうえお</string>
<int name="val" value="100" />
</map>


 テキストファイルの読み込みや保存などのページは→こちら


(関連記事)
【Android】res/raw リソースフォルダからテキストファイルを読み込む
【Android】assets フォルダからテキストファイルを読み込む
【Android】内部ストレージからテキストファイルを読み込む
【Android】内部ストレージにテキストファイルを保存する
【Android】SDカードからテキストファイルを読み込む
【Android】SDカードにテキストファイルを保存する
【汎用】ストリームからテキストファイルを読み込む(ストリームから読み込み、テキストエンコードして返す)
【汎用】ローカルシステム(Windows 等)から、テキストファイルを読み込む
【Applet/汎用】URL経由でWebサーバ上のテキストファイルを読み込む
【Applet】jar 内リソースからテキストファイルを読み込む
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ
【AndroidStudio】AndroidStudio 2.x で DDMS を表示する


category: Android

thread: プログラミング

janre: コンピュータ

tag: テキストファイル保存 
tb: 0   cm: --

【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ  


 これまで色々なテキストファイルの読み込み・保存関数を複数ページに渡って列挙してしまったので、一覧としてまとめてみる。説明等は簡略してあるので、詳細な解説や注意点など必要ならば、各記事を参照して貰いたい。例外処理・確認コードも省略する。定数も一番上の定義を共有とする(デフォルトのエンコードと読み込みバッファサイズのみ)。必要あれば、引数等を付け加えてオーバーロードしても良いだろう。

 これらは、1つのクラスにまとめても良いが、できれば各プラットフォーム用(Android, Applet, 汎用等)に分けて置いた方が無駄がなくて良いかも。

【共通】
ストリームからの読み込み・保存
ローカルシステムから、テキストファイルの読み込み・保存
ストリームからテキストを行読みする(OS依存)
URL経由で外部Webサーバ上(http)のテキストファイルを読み込む(ダウンロードする)
【Android】
res/raw フォルダから、テキストファイルの読み込み
assets フォルダから、テキストファイルの読み込み
内部ストレージから、テキストファイルの読み込み・保存
SDカードから、テキストファイルの読み込み・保存
エラーをSDカードに書き出す(別ページ)
プリファレンス機能で値の読み込み・保存(別ページ)
【Applet】
URL経由で同Webサーバ上のテキストファイルを読み込む
jar ファイル内から、テキストファイルを読み込む


■【共通】 ストリームからの読み込み・保存
//設定値
private static final String DEFAULT_ENCORDING = "UTF-8"; //デフォルトのエンコード
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);
}


//出力ストリームにてテキストを保存(汎用)
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
}
}
}

(解説) readStream(), loadText()
(解説) saveText()


■【共通】 ローカルシステム(Windows 等)から、テキストファイルの読み込み・保存
//ローカルシステム(Windows 等)から、テキストファイルを読み込む(汎用)
//(ex) String fileName = "C:/res/data/sample.txt"; //相対パスでも良い
// String text = loadTextLocal(fileName);

public static final String loadTextLocal(String fileName) throws IOException, FileNotFoundException {
InputStream is = new FileInputStream(fileName);
return loadText(is, DEFAULT_ENCORDING);
}


//ローカルシステム(Windows 等)に、テキストファイルを保存(汎用)
//(ex) String fileName = "C:/res/data/sample.txt"; //相対パスでも良い
// String text = "保存するテキスト";
// saveTextLocal(fileName, text);

public static final void saveTextLocal(String fileName, String text) throws IOException {
OutputStream os = new FileOutputStream(fileName);
saveText(os, text, DEFAULT_ENCORDING);
}

(解説) loadTextLocal()


■【共通】ストリームからテキストを行読みする(OS依存)
/**<h1>ストリームからテキストを行読みする(行セパレータを指定)</h1>
* <p>行末にセパレータを付ける。エンコードはシステム依存となる。</p>
* @param is : 入力ストリーム
* @param lineSep : 行セパレータ("\n" など)
* @return<b>String</b> : 読み込んだテキスト
* @throws IOException
*/
public static final String readLinesText(final InputStream is, final String lineSep) throws IOException {
final StringBuilder str = new StringBuilder();
final BufferedReader br = new BufferedReader(new InputStreamReader(is));
try {
while (br.ready()) {
str.append(br.readLine()); //終端文字は含まない
str.append(lineSep); //改行コードなど
}
return str.toString();
} finally {
br.close();
str.setLength(0);
}
}

/**<h1>ストリームからテキストを行読みする(OS依存の改行が付く)</h1>
* <p>行末にセパレータ(改行)を付ける。エンコードはシステム依存となる。</p>
* @param is : 入力ストリーム
* @return<b>String</b> : 読み込んだテキスト
* @throws IOException
*/
public static final String readLinesText(final InputStream is) throws IOException {
return readLinesText(is, System.getProperty("line.separator")); //OS依存 改行コード
}


/**<h1>行ごとに文字列を読み込んでリストで返す(OS 依存)</h1>
* <p>各要素の終端は改行を含まない。</p>
* @param is : 入力ストリーム
* @return<b>List<String></b> : 行ごとの文字列
* @throws IOException
*/
public static final List<String> readLinesList(final InputStream is) throws IOException {
final List<String> list = new ArrayList<String>();
final BufferedReader br = new BufferedReader(new InputStreamReader(is));
try {
while (br.ready()) {
list.add(br.readLine()); //終端文字は含まない
}
return list;
} finally {
br.close();
}
}

(解説) readLinesText()


■【Android】 res/raw フォルダから、テキストファイルの読み込み
// res/raw フォルダから、リソース名でテキストファイルを読み込む(Android 用)
//(ex) String resName= "sample"; // "res/raw/sample.txt" の場合
// String text = loadTextRaw(resName, this); //this は起動 Activity 等(Context)

public static final String loadTextRaw(String resName, Context context) throws IOException, FileNotFoundException {
final int id = context.getResources().getIdentifier(resName, "raw", context.getPackageName());
if (id == 0) { //エラーにはならない
throw new FileNotFoundException();
}
InputStream is = context.getResources().openRawResource(id);
return loadText(is, DEFAULT_ENCORDING);
}


// res/raw フォルダから、リソースID でテキストファイルを読み込む(Android 用)
//(ex) int rawId = R.raw.text; // "res/raw/sample.txt" の場合
// String text = loadTextRaw(rawId, this); //this は起動 Activity 等(Context)

public static final String loadTextRaw(int rawId, Context context) throws IOException, FileNotFoundException {
if (rawId == 0) {
return null;
}
InputStream is = context.getResources().openRawResource(rawId);
return loadText(is, DEFAULT_ENCORDING);
}

(解説) loadTextRaw()


■【Android】 assets フォルダから、テキストファイルの読み込み
// assets フォルダから、テキストファイルを読み込む(Android 用)
//(ex) String fileName = "res/data/sample.txt"; // assets/ 以下の相対パス
// String text = loadTextAsset(fileName, this); //this は起動 Activity 等(Context)

public static final String loadTextAsset(String fileName, Context context) throws IOException, FileNotFoundException {
final AssetManager assetManager = context.getAssets();
InputStream is = assetManager.open(fileName);
return loadText(is, DEFAULT_ENCORDING);
}

(解説) loadTextAsset()


■【Android】 内部ストレージから、テキストファイルの読み込み・保存
// 内部ストレージから、テキストファイルを読み込む(Android 用)
//(ex) String fileName = "sample.txt"; // "data/data/[パッケージ名]/files/sample.txt" になる
// String text = loadTextLocalStorage(fileName, this); //this は起動 Activity 等(Context)

public static final String loadTextLocalStorage(String fileName, Context context)
throws IOException, FileNotFoundException {
InputStream is = context.openFileInput(fileName);
return loadText(is, DEFAULT_ENCORDING);
}


//内部ストレージに、テキストファイルを保存する(Android 用)
// (ex) String fileName = "sample.txt"; // "data/data/[パッケージ名]/files/sample.txt" となる
// String text = "保存するテキスト";
// saveTextLocalStorage(fileName, text, this); //this は起動 Activity 等(Context)

public static final void saveTextLocalStorage(String fileName, String text, Context context) throws IOException {
// "data/data/[パッケージ名]/files/" 直下に保存。他アプリアクセス不可(MODE_PRIVATE)
OutputStream os = context.openFileOutput(fileName, Context.MODE_PRIVATE);
saveText(os, text, DEFAULT_ENCORDING);
}

(解説) loadTextLocalStorage()
(解説) saveTextLocalStorage()


■【Android】 SDカードから、テキストファイルの読み込み・保存
(※) Android4.4(API 19)あたりから内部ストレージの仮想パスに変わった模様
// SDCard のマウント状態のチェックする(Android 用)
public static final boolean isMountSDCard() {
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 用)
//(ex) String fileName = "sample.txt"; // "mnt/sdcard/sample.txt" or "sdcard/sample.txt" になる(端末による)
// String text = loadTextSDCard(fileName);

public static final String loadTextSDCard(String fileName) throws IOException {
if (!isMountSDCard()) { //マウント状態のチェック
throw new IOException("No Mount");
}
final String absPath = toSDCardAbsolutePath(fileName); //SDCard 内の絶対パスに変換
InputStream is = new FileInputStream(absPath);
return loadText(is, DEFAULT_ENCORDING);
}


//SDCard に、テキストファイルを保存する(Android 用)
// (ex) String fileName = "sample.txt"; // "mnt/sdcard/sample.txt" or "sdcard/sample.txt" になる(端末による)
// String text = "保存するテキスト";
// saveTextSDCard(fileName, text);

public static final void saveTextSDCard(String fileName, String text) throws IOException {
if (!isMountSDCard()) {
throw new IOException("No Mount");
}
final String absPath = toSDCardAbsolutePath(fileName); //SDCard 内の絶対パスに変換
OutputStream os = new FileOutputStream(absPath);
saveText(os, text, DEFAULT_ENCORDING);
}

(解説) loadTextSDCard(), isMountSDCard(), toSDCardAbsolutePath(), getSDCardDir()
(解説) saveTextSDCard()
(解説) saveText()


■【共通】 URL経由で外部Webサーバ上(http)のテキストファイルを読み込む(ダウンロードする)
//URL経由でWebサーバ上(http)のテキストファイルを読み込む(Android, Applet, 汎用)
//(ex) String httpUrl = "http://www.xxx.com/sample.txt"; //WebサイトのURL(http)
// String text = loadTextHttp(httpUrl, "UTF-8", 10000); //Timeout:10秒
//(Android) <uses-permission android:name="android.permission.INTERNET" /> が必要。

public static final String loadTextHttp(String httpUrl, String charsetName, int connectTimeout)
throws SocketTimeoutException, IOException {
final URL url = new URL(httpUrl);
final HttpURLConnection con = (HttpURLConnection)url.openConnection();
con.setConnectTimeout(connectTimeout); //接続タイムアウト
con.setRequestMethod("GET");
con.connect();
InputStream is = con.getInputStream();
return loadText(is, DEFAULT_ENCORDING);
}

(参考) JSON を PHP から送信して、Java で受信する
(参考) 画像を PHP から送信して、Android で受信する


■【Applet/汎用】 URL経由で同Webサーバ上のテキストファイルを読み込む
//URL経由でWebサーバ上のテキストファイルを読み込む(Applet, 汎用)
//(ex) String fileName = "res/data/sample.txt"; //html からの相対パス
// String text = loadTextURL(new URL(getCodeBase(), fileName)); //同サーバ上の場合

public static final String loadTextURL(URL url) throws IOException {
InputStream is = url.openStream();
return loadText(is, DEFAULT_ENCORDING);
}

(解説) loadTextURL()


■【Applet】 jar ファイル内から、テキストファイルを読み込む
//クラスから自身の jar の URL を取得する(jar 内の .class からのみ)
public static final URL getJarFileURL(Object object) {
try {
final ClassLoader loader = object.getClass().getClassLoader();
final String name = object.getClass().getName().replace('.', '/') + ".class";
final URL url = loader.getResource(name);
final Pattern p = Pattern.compile("^jar\\:(.+?\\.jar)\\!\\/(.*)");
final Matcher m = p.matcher(url.toString());
if (m.matches()) {
final MatchResult res = m.toMatchResult();
return new URL(res.group(1));
}
} catch (Exception e) {
//MalformedURLException, ClassCastException, NullPointerException, ...
}
return null; //取得失敗した場合はすべて null
}

//ファイルパスから jar 内のリソース URL を作成する
public static final String toJarURL(String fileName, Object context) {
final URL url = getJarFileURL(context); //jar の url を取得
if (url == null) {
return null; //失敗
}
return "jar:" + url.toString() + "!/" + fileName; //JAR URL 構文にするだけ
}


//jar ファイル内から、テキストファイルを読み込む(Applet 用)
//(ex) String fileName = "res/data/sample.txt"; //jar 内相対パス
// String text = loadTextJar(fileName, this); //this は起動 Applet 等(jar 内の .class)

public static final String loadTextJar(String fileName, Object context) throws IOException, FileNotFoundException {
final String jarUrl = toJarURL(fileName, context);
if (jarUrl == null) { //見つからないとき
throw new FileNotFoundException();
}
final URL url = new URL(jarUrl);
InputStream is = url.openStream();
return loadText(is, DEFAULT_ENCORDING);
}

(解説) getJarFileURL()
(解説) toJarURL()
(解説) loadTextJar()


 Android のプリファレンス機能を使って読み込みや保存をするには→こちら


(関連記事)
【Android】エラーをSDカードに書き出す
【Android】Preference 機能を使ってデータを読み込み・保存する
【Android】assets フォルダから画像ファイルを読み込む
【Android】SDカードから画像ファイルを読み込む
【Android】SDカードに画像ファイルを保存する(png)
【Android】SDカードに画像ファイルを保存する(jpg)
【Android】内部ストレージから画像ファイルを読み込む
【Android】内部ストレージに画像ファイルを保存する(png)
【Android】内部ストレージに画像ファイルを保存する(jpg)



category: Android

thread: プログラミング

janre: コンピュータ

tag: テキストファイル読み込み  テキストファイル保存 
tb: 0   cm: --

【Android】【Java】SDカードにテキストファイルを保存する  


 保存もついでなので簡単なものを書いて置く。前回の「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 機能を使ってデータを読み込み・保存する



category: Android

thread: プログラミング

janre: コンピュータ

tag: テキストファイル保存  SDカード 
tb: 0   cm: --

【Android】【Java】内部ストレージにテキストファイルを保存する  


 ついでなので、前回の「内部ストレージからテキストファイルを読み込む」のテストにも使えるように、簡単な保存機能も書いてみる。ストリームにて書き込みも必要なので、簡単なものを用意した。読み込みの loadText() はサイズ不定でも良いように、最後まで while ループで読み込んでいるが、保存の場合はサイズがわかってるので、1つのメソッドで済ませている。あまりに巨大なファイルでなければ、これで十分だろう。正確にはファイルを保存というより、出力先に転送みたいな感じなのだが、出力先をファイルに限定して、loadText() と対に使っても良いだろう。

//設定値
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
}
}
}


//内部ストレージに、テキストファイルを保存する(Android 用)
public static final void saveTextLocalStorage(String fileName, String text, Context context) throws IOException {
// "data/data/[パッケージ名]/files/" 直下に保存。他アプリアクセス不可(MODE_PRIVATE)
OutputStream os = context.openFileOutput(fileName, Context.MODE_PRIVATE);
saveText(os, text, DEFAULT_ENCORDING);
}


//メインでは... (※例外処理は省略)
String fileName = "sample.txt"; // "data/data/[パッケージ名]/files/sample.txt" となる
String text = "保存する文字列";
saveTextLocalStorage(fileName, text, this); //this は起動した Activity が良い(Context)
//ファイルが保存されていれば成功(エミュレータならDDMSで確認できる)

 文字エンコーディングは読み込みに合わせて "UTF-8" にした方が良いだろう。他のものにしたいなら、ストリームに渡す前に変更してやれば良い。

 実機の場合は確認しずらいかも知れないが、端末のアプリケーション管理から、該当アプリの情報を覗いてみると、「保存先」のような項目があり、データ容量が増えている事でもわかる(メニューは端末による)。

 ちなみにファイルの削除は Context.deleteFile() で簡単にできる。

 Android にはその他に、外部ストレージ機能というものもある。一番身近なものはSDカードだ。これはエミュレータでも実験できるので、次回はそれらに必要ないくつかの関数を組み合わせて、SDカードからテキストファイルを読み込む機能を作ってみよう。

 テキストファイルの読み込みや保存をまとめたページは→こちら


(関連記事)
【Android】内部ストレージからテキストファイルを読み込む
【Android】内部ストレージから画像ファイルを読み込む
【Android】内部ストレージに画像ファイルを保存する(png)
【Android】内部ストレージに画像ファイルを保存する(jpg)
【Android】SDカードにテキストファイルを保存する
【Android】【Applet】【Java】テキストファイルの読み込み・保存 まとめ
【Android】Preference 機能を使ってデータを読み込み・保存する



category: Android

thread: プログラミング

janre: コンピュータ

tag: テキストファイル保存  内部ストレージ 
tb: 0   cm: --
IS<インフィニット・ストラトス> アーキタイプ・ブレイカー
キルドヤ


プロフィール

Twitter

検索フォーム

全記事一覧

カテゴリ

ユーザータグ

最新記事

リンク

PR

▲ Pagetop