ファイルアクセス
androidのファイルにアクセスするには、javaの標準のAPIを使う事もできるが、 アプリケーション配下のファイルにアクセスするための、android独自のAPIが用意されている。
アプリケーション配下のファイル格納領域としては以下の3種類がある。
- 「data」デレクトリ
- 「assets」デレクトリ
- 「raw」デレクトリ
また、AndroidのOSはLinuxであり、アクセス権限があるため、どのデレクトリにもアクセスできるわけではないが、アプリケーション配下外のデレクトリのファイルであっても、 SDカードなどのアクセスが許されているデレクトリであれば、javaの標準のファイルアクセスAPIを使ってアクセス可能である。
それぞれのファイルアクセスの方法について、順番にみていくことにする。
「data」デレクトリのファイルにアクセス(ContextWrapperクラスのメソッド)
androidには、アプリケーションごとにアプリケーション専用の「data」デレクトリが用意されている。
このデレクトリは「/data/data/プロジェクトを作成する際に指定したパッケージ名」となる。
「プロジェクトを作成する際に指定したパッケージ名」は、ContextWrapperクラスのgetPackageName()メソッドを使って得る事ができる。
この「data」デレクトリには目的ごとに、それぞれ専用のサブデレクトリが作られて利用されることになる。
例えば、データーベースには「databases」デレクトリが,Preference(設定ファイル)の保存には「shared_pref」デレクトリが使われる決まりになっている。
そして、ファイルアクセス専用のサブデレクトリとしては「files」が使われる。
アプリケーション専用の「data」デレクトリに対してファイルアクセスをおこなうには、このfilesデレクトリに対してアクセスする事になる。
ContextWrapperクラスには、この「data」デレクトリへのファイルアクセスのために、以下のようなメソッドが用意されている。
ContextWrapperクラスのメソッド
- File getFilesDir()メソッド
filesデレクトリを示すFileクラスのオブジェクトを返す。
このデレクトリは次に示すopenFileOutput,openFileInputメソッドでのファイルアクセス先となるデレクトリである。 - FileOutputStream openFileOutput(String fileName, int mode)メソッド
filesデレクトリのファイルにデータを書込むために、ファイルをオープンする。
javaの標準のファイルアクセスクラスであるFileOutputStreamクラスを返すので、これを使ってjavaの標準のファイルアクセスのAPIが利用できる。
第1引数fileNameには、オープンするファイル名を指定する。
第2引数modeには、ファイルの操作モードを指定する。(操作モードについては後述する。) - FileInputStream openFileInput(fileName name)メソッド
filesデレクトリのファイルにデータを読込むために、ファイルをオープンする。
第1引数fileNameには、オープンするファイル名を指定する。
javaの標準のファイルアクセスクラスであるFileInputStreamクラスを返すので、これを使ってjavaの標準のファイルアクセスのAPIが利用できる。 - String[] fileList()メソッド
filesデレクトリのファイルのリストを、文字列配列に格納して返す。
- boolean deleteFile(String fileName)メソッド
filesデレクトリのファイルを削除する。
削除に成功した場合はtrueを,失敗した場合はfalseを返す。 - File getFileStreamPath(String fileName)メソッド
filesデレクトリ配下のファイル名がfileNameであるファイルを示す、Fileクラスのオブジェクトを返す。 - File getDir(String dirName, int mode)メソッド
「data」デレクトリの配下に、filesデレクトリとは異なるdirNameで指定された独自のファイルアクセス用のデレクトリを示す、Fileクラスのオブジェクトを返す。
この独自のファイルアクセス用のデレクトリは、"app_"+dirNameという名前のデレクトリとなる。
もし、"app_"+dirNameという名前のデレクトリが存在しない場合には、このデレクトリが新たに作成される。
第2引数modeにはopenFileOutputメソッドと同様、ファイルの操作モードを指定する。
ActivityはContextWrapperクラスを継承しているので、Activityクラスを継承したクラスよりこれらのメソッドを利用する事ができる。
操作モードの指定
openFileOutputメソッドとgetDirメソッドの第2引数には、下記のモードが指定できる。
- MODE_PRIVATE
他のアプリケーションからアクセス不可 - MODE_APPEND
既にファイルが存在する場合は追加で書込みをおこなう。 - MODE_WORLD_READABLE
他のアプリケーションから読込み可能なファイルとしてオープンする。 - MODE_WORLD_WRITEABLE
他のアプリケーションから書込み可能なファイルとしてオープンする。
複数のモードを指定する場合は|で連結して指定する。
例えば、他のアプリケーションから読込みも書込みも可能にするには、「MODE_WORLD_READABLE|MODE_WORLD_WRITEABLE」を指定する。
以下にContextWrapperクラスのメソッドを使ってfilesデレクトリにアクセスする例を示す。
リスト1-filesデレクトリにアクセスする(FileAccess1Activity.java)
このプログラムを実行し、EditTextに文字列を入力した後、「書込み」ボタンを押下すると、 「data」デレクトリにfilesデレクトリが作成され、そのデレクトリ内のテキストファイルxxx.txtに、入力した文字列が書き込まれる。
この様子は、DDMパースペクティブのファイルエクスプローラにて、「/data/data/プロジェクトを作成する際に指定したパッケージ名/files/」 デレクトリを参照する事で確認する事ができる。
リスト1のコードの、34行目ではgetFilesDirメソッドを使ってfilesデレクトリのFileオブジェクトを取得している。
50~62行目はファイル書込みの例である。
51行目のopenFileOutputメソッド以外は、標準のjavaのファイルアクセスAPIが使われている。
78~94行目はファイル読込みの例である。
これも、79行目のopenFileInputメソッド以外は標準のjavaのファイルアクセスAPIが使われている。
107~112行目は、fileListメソッド使っってfilesデレクトリのファイルリストをTextViewに表示する例である。
125行目は、deleteFileメソッド使っってファイルを削除する例である。
「書込み」ボタンを押下した後で、「fileListの表示」ボタンを押下すると、保存したファイル名が表示される。
この後、ファイルの「削除ボタン」を押下して、再度、「fileListの表示ボタン」を押下すると、削除したファイル名が表示されなくなるのがわかる。
filesデレクトリのサブデレクトリにアクセスする
これらのfilesデレクトリ にアクセスするメソッドは、いずれもファイル名の指定にxxx/yyy.txtのような、ファイルセパレータ(パス付きのファイル名)を指定する事はできない。
このため、 filesデレクトリ配下にサブデレクトリを作成してこれにアクセスする手段が無いことになる。
しかし、以下のようにFileクラスを利用すると、この問題を解決する事ができる。
リスト11-filesデレクトリ配下にサブデレクトリを作成して、このデレクトリのファイルにアクセスする(FileAccess7Activity.java)
このプログラムを実行して、書込みボタンを押下、DDMパースペクティブのファイルエクスプローラを参照すると、 以下の図のようにsubdirデレクトリにファイルが保存されているのが確認できる。
サブデレクトリにアクセスするには、openFileOutputメソッド,openFileInputメソッドの 代わりに、57行目,84行目のようにjava標準のファイルアクセスAPIを使う事である。
「data」デレクトリの独自のファイルアクセス用のデレクトリを利用する
getDirメソッドを利用すると、独自のファイルアクセス用のデレクトリを作成して、アクセスする事ができる。
以下に、その例を示す。
リスト12-独自のファイルアクセス用のデレクトリを利用する(FileAccess8Activity.java)
独自のファイルアクセス用のデレクトリは、指定したデレクトリ名の先頭に「app_」の文字列が付く事になる。
このプログラムを実行して、書込みボタンを押下、DDMパースペクティブのファイルエクスプローラを参照すると、 以下の図のようにapp_my_filesデレクトリにファイルが保存されているのが確認できる。
「assets」デレクトリのファイルへのアクセス
プロジェクトのassetsデレクトリにファイルを配置して、このファイルを読込むこともできる。
このassetsデレクトリのファイルは、読込み専用となる。
また、assetsデレクトリには、サブデレクトリを作成してこのサブデレクトリに保存したファイルにも、アクセスする事ができる。
以下に、assetsデレクトリのファイルにアクセスをおこなうプログラムの例を示す。
リスト2-assetsデレクトリのファイルにアクセスをおこなう(FileAccess2Activity.java)
プロジェクトのassetsデレクトリに「xxx.txt」ファイルを保存して、 このプログラムを実行し、「assetsデレクトリのファイル読込み」ボタンを押下すると、保存したテキストファイルの内容が、TextViewに表示されます。
39~58行目は、ファイル読込みの部分である。
リスト1の78~94行目のコードと比較すると、40行目と41行目だけが異なるだけで、後はまったく同じようにアクセスできる事がわかる。
72行目にあるように、AssetManagerクラスのlistメソッドを実行するとassetsデレクトリのファイルリストを取得できる。
「assetsデレクトリのファイルリストを表示」ボタンを押下して、このメソッドを実行してみると「xxx.txt」の他に、下図のようにimages,sounds,webkitが表示されている。
このフォルダーに、イメージ画像や,音楽ファイル,htmlファイルを保存して使える事を意味しているのかな?
「raw」デレクトリのファイルへのアクセス
プロジェクトのresデレクトリの直下にrawという名前のデレクトリを作成して、この中にファイルを保存すると、リソースIDを指定してファイルを読込む事ができる。
リソースIDは、ファイル名の拡張子を除いた名前と同じになるため、ファイル名として使える文字はa~zの小文字、アンダーバー(_)、ピリオド(.)のみとなる。
リソースとしてアクセスをおこなうため、このassetsデレクトリのファイルもassetsデレクトリと同様、読込み専用となる。
assetsデレクトリとの違いは、assetsデレクトリはファイル名を使ってファイルにアクセスするのに対して、「res/raw」デレクトリのファイルは、リソースIDを使ってファイルにアクセスする点である。
以下に、rawデレクトリのファイルにアクセスをおこなう、プログラムの例を示す。
リスト3-rawデレクトリのファイルにアクセスをおこなう(FileAccess3Activity.java)
37~56行目は、ファイル読込みの部分である。
リスト1やリスト2のファイル読込みコードと比較すると、38行目と39行目だけが異なる事になる。
アプリケーション配下外のデレクトリのファイルへのアクセス-SDカード
ファイルのアクセス権があれば、android固有のファイルアクセスのAPIではなく、 java標準のAPIを使って、アプリケーション配下以外のファイルにもアクセスする事ができる。
以下に、java標準のAPIを使って、SDカードのファイルにアクセスするプログラムの例を示す。
リスト4-SDカードのファイルにアクセスをおこなう(FileAccess5Activity.java)
SDカードのファイルを読込むだけであれば必要無いが、SDカードのファイルを書込むためには、 マニュフェストファイルに以下の18行目のようにパーミッションの設定を追加する必要がある。
リスト5-SDカードのファイルにアクセスをおこなう(AndroidManifest.xml)
リスト4のコードに説明を加えると、SDカードのファイルにアクセスするには、SDカードのデレクトリを知る必要がある。
このデレクトリは、32行目のようにEnvironment.getExternalStorageDirectoryメソッドにより取得する事ができる。
49~60行目は、ファイル書込みの例である。
リスト1~3のコードと比較すると、49行目の部分だけが異なる事がわかる。
75~91行目は、ファイル読込みの例である。
これも、リスト1~3のコードと比較すると、76行目の部分だけが異なる事がわかる。
簡易ファイルエクスプローラ&テキストビュアーをつくる。
最後に、java標準のファイルアクセスAPIを使って、ルートデレクトリをたどってテキストファイルの内容を表示する、プログラムのサンプルを示す。
手抜きプログラムなので、いろいろとバギーなところもあるが、その点はご容赦いただきたい。
このプログラムを実行すると、以下のようにListViewにファイルリストが表示される。
リストの項目をクリックすると、その項目がデレクトリであればそのデレクトリのファイルリストがリスト表示され、 ファイルであればファイルの内容がテキスト表示される。
リスト6-ファイルリストを表示するメインアクティビティクラス(FileAccess6Activity.java)
リスト7-テキスト表示をおこなうサブアクティビティクラス(SubActivity.java)
リスト8-マニュフェストファイル(AndroidManifest.xml)
リスト9-メインアクティビティのレイアウトファイル(main.xml)
リスト10-ListViewのレイアウトファイル(list_row.xml)
フォルダアイコンを表示するために、res/drawableフォルダに、フォルダアイコン画像「folder.gif」のファイルが必要です。
自分で作るのも面倒くさいので、 このサイトのフリー画像をダウンドーロードして、使わせて頂きました。
最後に
ここまで、ファイルアクセスの方法にについて述べてきたが、またまた、話が長くなってしまった。
アプリケーション配下のファイル格納領域のファイルを、異なるアプリケーションからアクセスする方法についても触れる予定であったが、 この話題はまた別の機会に譲ることにする。
- 追記
- アプリケーション配下のファイル格納領域のファイルを、異なるアプリケーションからアクセスする方法については、「他のアプリケーションのデータを利用する」を参照。