在android開發中文件操作使用的其實還是比較高頻的,之前我遇到這種需求都隨便寫寫,對此沒有一個比較全面的認識,所以想借這篇文章來梳理一遍。
由於需要讀寫文件,這包含了讀寫外部sd card的文件,所以需要添加對飲的讀寫權限
<!-- SDCard中創建與刪除文件權限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--讀取SDCard數據權限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- 向SDCard寫入數據權限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
1、獲取存儲路徑
android可能有兩個地方可以存儲文件,一是存放在sd卡中(如果有的話),另外就是存儲在內存卡中,那麼與此對應的就有兩組方法來獲取存儲路徑。
a、獲取sd卡相關路徑的方法
關於獲取sd卡相關路徑方法和獲取到的路徑的對應關係如下
Environment.getExternalStorageDirectory().getAbsolutePath()
/storage/emulated/0
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath())
/storage/emulated/0/DCIM
這兩個方法是通過Environment提供的方法來獲取sd卡路徑,可以看到的獲取的基本是sd卡的根路徑,而實際上/storage/emulated/0這個路徑代表是的第一行sd卡,當我們在該路徑下創建yoryky.txt文件時,實際手機上看到的路徑是/存儲盤/yoryky.txt,根本是找不到/storage/emulated/0這個路徑的。
另外我們還可以根據Context對象提供的方法來獲取sd卡的存儲路徑
getExternalCacheDir().getAbsolutePath()
/storage/emulated/0/Android/data/packagename/cache
該路徑會在sd卡下Android/data/路徑下創建packagename路徑並最終創建一個cahce目錄,在刪除app時,這個目錄也會被刪除。
getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath:
/storage/emulated/0/Android/data/packagename/files/Pictures
這個路徑是在上面講到cache目錄的同級目錄下創建一個files目錄,並在其中闖將存放圖片的Pictures目錄。getExternalFilesDir方法中可以傳多種參數,例如還可以傳Environment.DIRECTORY_DCIM這個參數一遍在files目錄下創建DCIM這個目錄。
由此我們知道獲取sd卡路徑的方法有兩套,一套是通過Environment類獲取packagename無關的路徑,一套是通過Context類獲取packagename相關的路徑,packagename路徑下可以有cache和files兩個目錄。
這裏的cache以及files兩個目錄在手機中的路徑爲/存儲盤/sd/Android/data/packagename/中。
b、獲取內存卡相關路徑方法
和獲取sd卡路徑不同,獲取內存卡路徑不能通過Environment類來獲取,只能通過Context來獲取
getCacheDir().getAbsolutePath()
/data/user/0/packagename/cache
getFilesDir().getAbsolutePath()
/data/user/0/com.yoryky.demo/files
可以看出Context提供的兩個方法,一個用來獲取cache目錄路徑,一個用來獲取files目錄路徑。這個的/data/user/0/代表多用戶(android 4.2版本開始支持多用戶)中的第一個用戶的存儲路徑,這個在手機上也是找不到的,實際上cache和files在手機中的路徑如下
看的出來,手機上cache和files的實際路徑爲/存儲盤/Android/data/packagename/。
2、讀寫sd card路徑中文件
第一小節講了獲取sd卡目錄路徑以及內存卡目錄路徑的方法,這裏先來說說讀寫sd卡路徑中文件的方法實現
a、寫sd卡中的文件方法
這裏通過FileOutputStream類來實現寫sd卡文件
/**
* 將內容寫入sd卡中
* @param filename 要寫入的文件名
* @param content 待寫入的內容
* @throws IOException
*/
public static void writeExternal(Context context, String filename, String content) throws IOException {
//獲取外部存儲卡的可用狀態
String storageState = Environment.getExternalStorageState();
//判斷是否存在可用的的SD Card
if (storageState.equals(Environment.MEDIA_MOUNTED)) {
//路徑: /storage/emulated/0/Android/data/com.yoryky.demo/cache/yoryky.txt
filename = context.getExternalCacheDir().getAbsolutePath() + File.separator + filename;
FileOutputStream outputStream = new FileOutputStream(filename);
outputStream.write(content.getBytes());
outputStream.close();
}
}
這個代碼很簡單,而且註釋也很詳細,這裏就不解釋了。
b、讀sd卡中的文件方法
通過FileInputStream來獲取sd卡中對應文件的內容
/**
* 從sd card文件中讀取數據
* @param filename 待讀取的sd card
* @return
* @throws IOException
*/
public static String readExternal(Context context, String filename) throws IOException {
StringBuilder sb = new StringBuilder("");
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
filename = context.getExternalCacheDir().getAbsolutePath() + File.separator + filename;
//打開文件輸入流
FileInputStream inputStream = new FileInputStream(filename);
byte[] buffer = new byte[1024];
int len = inputStream.read(buffer);
//讀取文件內容
while(len > 0){
sb.append(new String(buffer,0,len));
//繼續將數據放到buffer中
len = inputStream.read(buffer);
}
//關閉輸入流
inputStream.close();
}
return sb.toString();
}
通過FileInputStream對象遍歷便可以獲取對應文件中的內容。
3、讀寫內存卡中的文件
其實續寫內存卡中的文件方法和讀寫sd卡文件方法基本一致,就是文件路徑改變了而已。
a、寫內存卡中文件方法
這裏也直接給出實現
/**
* 寫Internal Card文件
* @param context
* @param filename
* @param content
* @throws IOException
*/
public static void writeInternal(Context context, String filename, String content) throws IOException{
//獲取文件在內存卡中files目錄下的路徑
File file = context.getFilesDir();
filename = file.getAbsolutePath() + File.separator + filename;
//打開文件輸出流
FileOutputStream outputStream = new FileOutputStream(filename);
//寫數據到文件中
outputStream.write(content.getBytes());
outputStream.close();
}
這裏還是通過FileOutputStream類來寫數據到文件中。
b、讀內存卡中文件方法
還是直接給代碼
/**
* 讀內存卡中文件方法
* @param context
* @param filename 文件名
* @return
* @throws IOException
*/
public static String readInternal(Context context,String filename) throws IOException{
StringBuilder sb = new StringBuilder("");
//獲取文件在內存卡中files目錄下的路徑
File file = context.getFilesDir();
filename = file.getAbsolutePath() + File.separator + filename;
//打開文件輸入流
FileInputStream inputStream = new FileInputStream(filename);
byte[] buffer = new byte[1024];
int len = inputStream.read(buffer);
//讀取文件內容
while(len > 0){
sb.append(new String(buffer,0,len));
//繼續將數據放到buffer中
len = inputStream.read(buffer);
}
//關閉輸入流
inputStream.close();
return sb.toString();
}
這裏依然通過FileInputStream來獲取文件中的數據。
到這裏讀寫sd卡以及內存卡中的文件方法就算是寫完了,實際上有這四個方法,我麼就可以封裝一個自己的FileUtil類來專門處理文件的讀寫操作了。這裏還是給一個demo地址吧,Android Demo.
4、參考文獻
這幾個參考文獻可好好看看,特別是前兩篇,第一篇說清楚了sd卡和內存卡路徑的作用和獲取方式,而第二篇說清了android中其它文件的獲取方式寶座資源文件以及assets中的文件獲取方式。