Android文件讀寫的幾種方式
Android的App可以讀寫的位置為:
一、內置data目錄下對應app名稱的目錄;
二、擴展SD卡(包括虛擬的內置SD卡和外置SD卡);
一、先說說內置data目錄下文件的讀寫。
內置data目錄即內部存儲,指的是應用內部獨有的存儲,這部分存儲的文件、數(shù)據(jù),只能被應用自身訪問到,其他應用都沒有權限訪問。
一般情況下,/data開頭的路徑都是內部存儲。而一般應用所能夠訪問到的就是下面幾個路徑,稱為應用內部私有存儲。
應用內部私有存儲:
/data/user/0/<包名>
/data/user/0/<包名>/files #存放文件數(shù)據(jù)
/data/user/0/<包名>/databases #存放Sqlite的數(shù)據(jù)庫文件
/data/user/0/<包名>/shared_prefs #存放SharedPreference的數(shù)據(jù)
/data/user/0/<包名>/cache #存放緩存文件
一旦App被卸載,系統(tǒng)將會移除內部存儲中相關應用的數(shù)據(jù)。
方式1:內置API讀寫
這個位置的讀寫有提供一套單獨的API來讀寫,無需申明特殊權限。
代碼中有個openFileInput的方法,這個方法是Android內置的,需放在Activity中才能執(zhí)行。
如下:
//讀取內置data目錄下文件
public String readDataFile(String fileName) {
String res = "";
try {
FileInputStream fin = openFileInput(fileName);
int length = fin.available();
byte[] buffer = new byte[length];
fin.read(buffer);
res = new String(buffer);
fin.close();
} catch (Exception e) {
e.printStackTrace();
Log.e("Exception", "readDataFile Error!" + e.getMessage());
}
return res;
}
//寫入內置data目錄下文件
private void writeDataFile(String fileName, String content) {
try {
FileOutputStream fut = openFileOutput(fileName, Context.MODE_PRIVATE | Context.MODE_APPEND);
byte[] bytes = content.getBytes();
fut.write(bytes);
fut.close();
} catch (Exception e) {
e.printStackTrace();
Log.e("Exception", "writeDataFile Error!" + e.getMessage());
}
}測試代碼:
String fileName="test.txt";
writeDataFile(fileName, "Hello Android");
String txt = readDataFile(fileName);
Log.e("txt", txt);方式2:獲取對應的data路徑后,通過普通的方法讀寫data中的文件。
手動獲取拼接data目錄下文件路徑,然后用通用的文件讀寫方式進行讀寫。
通用讀寫文件的輔助類,F(xiàn)ileHelper.java
package com.rc114.scanner;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.URLDecoder;
public class FileHelper {
public static String combinePath(String path1, String path2) {
File file1 = new File(path1);
File file2 = new File(file1, path2);
return file2.getPath();
}
/**
* 讀取文件
*
* @param filepath 文件路徑
*/
public static String readFile(String filepath) {
String encoding = "UTF-8";
return readFile(filepath, encoding);
}
/**
* 讀取文件,指定編碼
*
* @param filepath 文件路徑
*/
public static String readFile(String filepath, String encoding) {
try {
filepath = URLDecoder.decode(filepath, "utf-8");
File file = new File(filepath);
Long filelength = file.length();
byte[] filecontent = new byte[filelength.intValue()];
FileInputStream in = new FileInputStream(file);
in.read(filecontent);
in.close();
return new String(filecontent, encoding);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
/**
* 將字符串寫入文件
*
* @param filepath
* @param text
* @param isAppend
*/
public static void writeFile(String filepath, String text, boolean isAppend) {
try {
filepath = URLDecoder.decode(filepath, "utf-8");
File file = new File(filepath);
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
if (!file.exists()) {
file.createNewFile();
}
FileOutputStream f = new FileOutputStream(filepath, isAppend);
f.write(text.getBytes());
f.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void writeFile(String filepath, String text, String encodeing) {
try {
filepath = URLDecoder.decode(filepath, "utf-8");
File file = new File(filepath);
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
if (!file.exists()) {
file.createNewFile();
}
// FileOutputStream f = new FileOutputStream(filepath, "GBK");
// f.write(text.getBytes());
// f.close();
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(filepath), encodeing);
writer.append(text);
writer.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}測試代碼:
//獲取data目錄下對應包名根目錄
String dataDir = Environment.getDataDirectory().getPath() + "/data/" + packageName;
//拼接待讀寫文件路徑
String filepath = FileHelper.combinePath(dataDir, "test.txt");
//寫入文件
FileHelper.writeFile(filepath, "Hello", "utf-8");
//讀取文件
String txt = FileHelper.readFile(filepath);
Log.e("txt", txt);二、擴展SD卡文件讀寫
擴展SD卡文件即外部存儲,指的是是公共的存儲,這部分存儲理論上是全局可見的,所有的應用都可以訪問這部分數(shù)據(jù),一般情況下,路徑都是以/storage開頭的,比如說/storage/emulated/0就是屬于外部存儲,這個路徑的實際的掛載點是/data/media。又比如外置sdcard的路徑為/storage/13FC-0F0B。 相比較內部存儲一定會存在,外部存儲可能是sdcard或者通過otg掛載的U盤形式,所以可能出現(xiàn)沒有掛載的情況,所以所有的外部存儲要在使用前通過下面的方式判斷是否有被掛載。
/*檢查外部存儲是否可寫*/
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
/*檢查外部存儲是否可讀*/
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}訪問外部存儲需在AndroidManifest.xml文件中申明權限:
<!-- 存儲權限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" tools:ignore="ProtectedPermissions" />
安卓6.0以后,谷歌要求危險權限必須動態(tài)獲取,所以還要使用requestPermissions在運行時獲取權限。
private static String[] PERMISSIONS_STORAGE = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
private static int REQUEST_PERMISSION_CODE = 100;
//獲取權限
private void getPermission() {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, PERMISSIONS_STORAGE, REQUEST_PERMISSION_CODE);
} else {
boolean writable = isExternalStorageWritable();
boolean readable = isExternalStorageReadable();
Log.e("外部存儲讀寫", "寫:" + writable + "-讀:" + readable);
File root = Environment.getExternalStorageDirectory();//取得外部存儲根路徑
File[] files = root.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
Log.e("文件夾", files[i].toString());
}
}
}
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CODE) {
for (int i = 0; i < permissions.length; i++) {
Log.i("MainActivity", "申請的權限為:" + permissions[i] + ",申請結果:" + grantResults[i]);
}
}
}在Activity的onCreate事件中執(zhí)行getPermission()方法,動態(tài)獲取存儲權限。
完成了上面的操作后,在代碼:
File root = Environment.getExternalStorageDirectory();//取得外部存儲根路徑 File[] files = root.listFiles();
中,root.listFiles()可能會返回null,還是無法讀取或寫入文件。
查了下資料,Android 10 或更高版本,還需要做一個配置:在AndroidManifest.xml中,還需增加:android:requestLegacyExternalStorage="true"

利用上面的FileHelper.java類,測試寫入一個文件:
File root = Environment.getExternalStorageDirectory(); FileHelper.writeFile(FileHelper.combinePath(root.getPath(), "text.txt"), "Hello", false);
測試遍歷根目錄:
File root = Environment.getExternalStorageDirectory();
File[] files = root.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
Log.e("文件夾", files[i].toString());
}
if (files[i].isFile()) {
Log.e("文件", files[i].toString());
}
}
}輸出結果:

至此,完成了外部存儲的讀寫功能。
參考資料:
??????1.Android中的內部存儲和外部存儲
2.android - Environment.getExternalStorageDirectory() deprecation alternatives - Stack Overflow
總結
到此這篇關于Android文件讀寫的幾種方式的文章就介紹到這了,更多相關Android文件讀寫內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android ScrollView實現(xiàn)橫向和豎向拖動回彈效果
這篇文章主要為大家詳細介紹了Android ScrollView實現(xiàn)橫向和豎向拖動回彈效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-09-09
Android Studio 4.0新特性及升級異常問題的解決方案
這篇文章主要介紹了Android Studio 4.0新特性及升級異常的相關問題,本文給大家分享解決方案,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06

