Android文件讀寫
| 版本 |
修改內容 |
日期 |
修改人 |
| V1.0 |
原始版本 |
2013/2/25 |
skywang |
|
|
|
|
|
Android文件讀寫的有兩種方式。一種,是通過標准的JavaIO庫去讀寫。另一種,是通過Context提供的接口去讀寫。
兩種方式的原理是一樣的,只是API接口不同。下面分別對兩種方式進行介紹。
1 通過Java IO庫讀寫文件
當我們想讀寫公用的目錄,如圖片、提示音;或者讀寫外部擴展卡上的文件時,一般都選擇通過Java IO庫去讀寫。當通過Java IO庫去讀寫文件時,一般會用到Android Enviroment的接口(如讀取外部sdcard的路徑、狀態等)。
1.1 Android Enviroment
下面分別對Android Eviroment涉及到的函數和變量進行說明
表01_ Enviroment API接口
| Enviroment API接口 |
|
| API名稱 |
說明 |
| staticFile getDataDirectory() |
獲取Android的數據目錄。 |
| staticFile getDownloadCacheDirectory() |
獲取的Android下載/緩存內容的目錄。 |
| staticFile getExternalStorageDirectory() |
獲取Android的外部存儲目錄(即sdcard目錄)。 |
| staticFile getExternalStoragePublicDirectory(String type) |
獲取為特定類型的文件放在頂層的公共外部存儲目錄。 |
| staticString getExternalStorageState() |
獲取的主要外部存儲設備的當前狀態(即sdcard目錄的狀態)。 |
| staticFile getRootDirectory() |
獲取Android的根目錄。 |
| 返回設備是否有外部存儲設備的仿真。 |
|
| 返回主“外部存儲設備是否是可拆卸的。 |
|
表02_Enviroment sdcard卡狀態說明
| Enviroment 公用目錄參數 |
||
| 類型 |
名稱 |
說明 |
| 標准的鈴聲目錄 |
||
| 相機拍照或錄像文件的存儲目錄 |
||
| 下載目錄 |
||
| 電影目錄 |
||
| 音樂目錄 |
||
| 提示音目錄 |
||
| 圖片目錄 |
||
| 播客目錄 |
||
| 鈴聲目錄 |
||
表03_ Enviroment sdcard卡狀態說明
| Enviroment sdcard卡狀態說明 |
|
| 狀態名稱 |
說明 |
| 非法移除狀態:移除sdcard之前,沒有卸載sdcard。 |
|
| 檢查狀態:檢查sdcard的有效性 |
|
| 掛載狀態:sdcard卡已經成功掛載。 |
|
| 只讀狀態:sdcard已經掛載,但是是只讀的。 |
|
| NOFS狀態:識別到sdcard卡,但無法掛載。無法掛載原因,可能是sdcard無存儲介質,或者sdcard卡的文件系統與android無兼容。 |
|
| 移除狀態:sdcard成功移除。 |
|
| 共享狀態:識別到sdcard卡,但sdcard未掛載,而是作為mass storage等設備(如以u盤的方式連接到電腦上)。 |
|
| 無法掛載狀態:識別到sdcard卡,但無法掛載。無法掛載的原因,可能是sdcard的存儲介質部分損壞。 |
|
| 未掛載:識別到sdcard,但沒有掛載。 |
|
1.2 Android Enviroment實例
AndroidManifest.xml
<?xml version="1.0"encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="com.yarin.Android.HelloAndroid"
android:versionCode="1"
android:versionName="1.0">
<!-- 往SDCard寫入數據權限 -->
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:icon="@drawable/icon"android:label="@string/app_name">
<activity android:name=".HelloAndroid"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="5" />
</manifest>
HelloAndroid.java
package com.yarin.Android.HelloAndroid;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import java.io.*;
import android.os.Environment;
// 測試Enviroment環境變量
public class HelloAndroid extends Activity {
private static final String TAG = "skywang-->HelloAndroid";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
isSdcardMounted() ;
publicDirTest() ;
enviromentAPITest() ;
}
private boolean isSdcardMounted() {
String str = Environment.getExternalStorageState();
boolean ret = Environment.MEDIA_MOUNTED.equals(str);
Log.d(TAG, "isSdcardMounted ret="+ret);
return ret;
}
private void enviromentAPITest() {
Log.d(TAG, "isExternalStorageEmulated="+Environment.isExternalStorageEmulated());
Log.d(TAG, "isExternalStorageRemovable="+Environment.isExternalStorageRemovable());
File file = null;
file = Environment.getDataDirectory();
Log.d(TAG, "getDataDirectory()="+file.getPath());
file = Environment.getExternalStorageDirectory();
Log.d(TAG, "getExternalStorageDirectory()="+file.getPath());
file = Environment.getDownloadCacheDirectory();
Log.d(TAG, "getDownloadCacheDirectory()="+file.getPath());
file = Environment.getRootDirectory();
Log.d(TAG, "getRootDirectory()="+file.getPath());
}
private void publicDirTest() {
File file = null;
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_NOTIFICATIONS);
Log.d(TAG, "DIRECTORY_NOTIFICATIONS="+file.getPath());
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS);
Log.d(TAG, "DIRECTORY_ALARMS="+file.getPath());
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
Log.d(TAG, "DIRECTORY_DCIM="+file.getPath());
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
Log.d(TAG, "DIRECTORY_DOWNLOADS="+file.getPath());
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
Log.d(TAG, "DIRECTORY_MOVIES="+file.getPath());
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
Log.d(TAG, "DIRECTORY_MUSIC="+file.getPath());
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
Log.d(TAG, "DIRECTORY_PICTURES="+file.getPath());
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS);
Log.d(TAG, "DIRECTORY_PODCASTS="+file.getPath());
file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES);
Log.d(TAG, "DIRECTORY_RINGTONES="+file.getPath());
}
}
打印結果如下:
D/skywang-->HelloAndroid( 3076):isSdcardMounted ret=true
D/skywang-->HelloAndroid( 3076):DIRECTORY_NOTIFICATIONS=/mnt/sdcard/Notifications
D/skywang-->HelloAndroid( 3076):DIRECTORY_ALARMS=/mnt/sdcard/Alarms
D/skywang-->HelloAndroid( 3076):DIRECTORY_DCIM=/mnt/sdcard/DCIM
D/skywang-->HelloAndroid( 3076):DIRECTORY_DOWNLOADS=/mnt/sdcard/Download
D/skywang-->HelloAndroid( 3076):DIRECTORY_MOVIES=/mnt/sdcard/Movies
D/skywang-->HelloAndroid( 3076):DIRECTORY_MUSIC=/mnt/sdcard/Music
D/skywang-->HelloAndroid( 3076):DIRECTORY_PICTURES=/mnt/sdcard/Pictures
D/skywang-->HelloAndroid( 3076):DIRECTORY_PODCASTS=/mnt/sdcard/Podcasts
D/skywang-->HelloAndroid( 3076):DIRECTORY_RINGTONES=/mnt/sdcard/Ringtones
D/skywang-->HelloAndroid( 3076):isExternalStorageEmulated=false
D/skywang-->HelloAndroid( 3076):isExternalStorageRemovable=false
D/skywang-->HelloAndroid( 3076):getDataDirectory()=/data
D/skywang-->HelloAndroid( 3076):getExternalStorageDirectory()=/mnt/sdcard
D/skywang-->HelloAndroid( 3076):getDownloadCacheDirectory()=/cache
D/skywang-->HelloAndroid( 3076):getRootDirectory()=/system
1.3 Java IO庫讀寫實例
AndroidManifest.xml
<?xml version="1.0"encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yarin.Android.HelloAndroid"
android:versionCode="1"
android:versionName="1.0">
<!-- 往SDCard寫入數據權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application android:icon="@drawable/icon"android:label="@string/app_name">
<activity android:name=".HelloAndroid"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="5" />
</manifest>
HelloAndroid.java
package com.yarin.Android.HelloAndroid;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import java.io.*;
import android.os.Environment;
// 通過Java IO去讀寫文件
public class HelloAndroid extends Activity{
privatestatic final String TAG = "skywang-->HelloAndroid";
privateFile sdcardDir = Environment.getExternalStorageDirectory();
privatestatic final String TEST_FILE_NAME = "file.txt";
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
originalJavaIOWriteTest();
originalJavaIOReadTest();
}
privateboolean isSdcardMounted() {
returnEnvironment.MEDIA_MOUNTED.equals(
Environment.getExternalStorageState());
}
privatevoid originalJavaIOReadTest() {
if(!isSdcardMounted())
return;
try {
Filefile = new File(sdcardDir, TEST_FILE_NAME);
FileInputStream in =
new FileInputStream(file);
byte[] bb = new byte[64];
intlen=0;
while ((len=in.read(bb))!=-1) {
Log.d(TAG, "bb="+newString(bb, 0, len));
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void originalJavaIOWriteTest() {
if(!isSdcardMounted())
return;
try {
Filefile = new File(sdcardDir, TEST_FILE_NAME);
FileOutputStream out =
new FileOutputStream(file);
String str = "i am skywang!";
byte[] bb = str.getBytes();
for (int i=0; i<bb.length; i++)
out.write(bb[i]);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
打印結果如下:
D/skywang-->HelloAndroid( 3298): bb=i am skywang!
2 通過Context提供的接口去讀寫
Android的Context提供了API用來讀寫該Activity的私有文件;默認路徑是:/data/data/<包>/files/***.***
Context提供了openFileInput()、openFileOutput()、deleteFile()等操作文件。下面簡要進行說明
2.1 Context接口說明
public abstract FileInputStream openFileInput (String name)
作 用:打開Activity的私有文件,用於讀數據。
參數說明:
name —— 文件名
public abstract FileOutputStream openFileOutput (String name,int mode)
作 用:打開Activity的私有文件,用於寫數據。
參數說明:
name —— 文件名
mode —— 寫文件的方式,有一下幾種值可以選擇。
MODE_APPEND:將內容以追加的方式寫到文件末尾。
MODE_PRIVATE:默認的方式,創建的文件只能被本Activity所訪問。
MODE_WORLD_READABLE:Android API LEVEL 17以后不建議使用。
MODE_WORLD_WRITEABLE:Android API LEVEL 17以后不建議使用。
public abstract String[] fileList ()
作 用:返回Activity私有的文件名組成的列表。
參數說明:無
public abstract boolean deleteFile (String name)
作 用:刪除Activity私有的文件。
參數說明:name —— 文件名
2.2 Context實例
HelloAndroid.java
package com.yarin.Android.HelloAndroid;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import java.io.*;
import android.os.Environment;
public class HelloAndroid extends Activity{
privatestatic final String TAG = "skywang-->HelloAndroid";
privatestatic final String TEST_FILE_NAME = "file.txt";
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//讀寫測試
activityFileWriteTest();
activityFileReadTest();
//列出當前文件
listActivityFiles();
//刪除后再列舉
Log.d(TAG,"deleteFile "+TEST_FILE_NAME);
deleteFile(TEST_FILE_NAME);
listActivityFiles();
}
//fileList接口測試
privatevoid listActivityFiles() {
String[]arrStr = fileList();
for(int i=0; i<arrStr.length; i++)
Log.d(TAG,"index="+i+", file_name ="+arrStr[i]);
}
//openFileInput接口測試
privatevoid activityFileReadTest() {
try {
FileInputStream in = openFileInput(TEST_FILE_NAME);
byte[] bb = new byte[64];
int len = in.read(bb);
Log.d(TAG,"bb="+new String(bb, 0, len));
in.close();
} catch (FileNotFoundException e) {
Log.d(TAG,"read file "+TEST_FILE_NAME+" not exist!");
} catch (IOException e){
e.printStackTrace();
}
}
//openFileOutput接口測試
privatevoid activityFileWriteTest() {
try {
FileOutputStream out =openFileOutput(TEST_FILE_NAME,MODE_WORLD_READABLE);
Stringstr = "this is a activity file test.";
out.write(str.getBytes());
out.close();
} catch (FileNotFoundException e) {
Log.d(TAG,"write file "+TEST_FILE_NAME+" not exist!");
} catch (IOException e){
e.printStackTrace();
}
}
}
打印結果如下:
D/skywang-->HelloAndroid( 3414): bb=thisis a activity file test.
D/skywang-->HelloAndroid( 3414):index=0, file_name =file.txt
D/skywang-->HelloAndroid( 3414):deleteFile file.txt
文件保存路徑為:/data/data/com.yarin.Android.HelloAndroid/files/file.txt
說明:不同的實例,保存路徑可能不一樣!
參考文件:
1,Android API文檔
2,Java API文檔
3,Android實現數據存儲技術:http://www.cnblogs.com/hanyonglu/archive/2012/03/01/2374894.html
