Android的文件存储分为内部存储和外部存储。
内部存储
使用内部存储保存文件,默认情况下,保存的文件是应用的私有文件,其他应用不能访问这些文件。当我们的应用被用户卸载时,这些文件也会相应的被移除。
我们可以使用openFileOutput(String name, int mode)来创建一个私有文件。该方法会返回一个FileOutputStream。参数name为文件的名字,参数mode为创建文件的模式,一般选择Context.MODE_PRIVATE(表明该文件为私有文件,如果有同名文件将会被替换)。其他可选模式有:
MODE_APPEND 表明该文件为私有文件,在写入数据时,如果文件已经存在,则将数据写入到文件的结尾,而不是擦除它。
MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE 表明该文件可以与其他应用共享。Android4.2被废弃。
下面方法将创建一个myfiles文件,文件位置位于/data/data/(packageName)/files目录下
String filename = "myfiles";
String fileContents = "Hello world";
try{
FileOutputStream fos = openFileOutput(filename,Context.MODE_PRIVATE);
fos.write(fileContents.getBytes());
fos.close();
}catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
要从内部读取文件,调用openFileInput(String name)传递一个文件名。这将会返回一个FileInputStream。
下面方法将会从内部存储中读取一个myfiles文件
String filename = "myfiles";
try {
FileInputStream fis = openFileInput(filename);
byte[] data = new byte[fis.available()];
fis.read(data);
String fileContents = new String(data);
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
如果只是想要保存一些应用的缓存数据。而不是永久保存这些数据,应该使用getCacheDir()来打开一个File。文件位置位于/data/data/(packageName)/cache目录下。当手机的存储空间不足时,系统可能会删除这些缓存文件来回收空间。但我们不应该依赖系统,而应该自行维护这些缓存文件以保持在一个合理的大小。当应用被卸载时,这些文件也会被删除。
String cacheFilename = "myCacheFile";
String cacheContents = "我是缓存";
try{
File file = new File(getCacheDir(), cacheFilename);
FileOutputStream fos = new FileOutputStream(file);
fos.write(cacheContents.getBytes());
fos.close();
} catch (FileNotFoundException e){
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
其他的一些实用方法
getFilesDir() 该方法会返回内部存储文件系统目录的绝对路径 即 /data/data/(packageName)/files目录。
getDir(String name, int mode) 会在内部存储空间内即(/data/data/(packageName)/files)创建或打开现有的目录。
deleteFile(String name) 删除保存在内部存储的文件
fileList() 返回保存在内部存储上的一系列文件(不包括缓存里面的)
外部存储
首先,外部存储不是指的sd卡。该存储可能是可移除的存储介质(sd卡)或内部(不可移除)存储。保存到外部存储的文件是全局可读取文件。
要想读取或写入外部存储上的文件,需要获得READ_EXTERNAL_STORAGE或WRITE_EXTERNAL_STORAGE系统权限。例如:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
在我们使用外部存储之前,应该始终检查外部存储是否处于可用状态。调用getExternalStorageState()方法可以检查外部存储处于什么状态。以下代码可以检查外部存储的可用性。
public boolean isExternalStorageOK() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
getExternalStorageState()方法将返回外部存储的状态(例如介质共享到计算机,缺失,错误移除等)。
我们可在外部存储保存可以与别的应用共享的文件,以便其他应用可以访问这些文件。执行此操作时,我们应该使用共享的公共目录之一。例如Music/,Pictures/,Ringtones/等。
我们可以调用getExternalStoragePublicDirectory(String type)并向其传递相应的目录类型。例如Environment.DIRECTORY_MUSIC,Environment.DIRECTORY_PICTURES,Environment.DIRECTORY_RINGTONES或其他类型。系统的媒体扫描程序可将这些文件正确的归类。以下方法可以在公共图片目录中创建一个新相册:
public File getAlbumStorageDir(String albumName) {
// Get the directory for the user's public pictures directory.
File file = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), albumName);
if (!file.mkdirs()) {
Log.e(LOG_TAG, "Directory not created");
}
return file;
}
我们可以使用外部存储保存应用的私有文件。通过调用getExternalFilesDir(String type)来使用外部存储上的私有目录。可以传入一个子目录的类型(例如Environment.DIRECTORY_MOVIES)。如果不需要特定的媒体目录,可以传入一个null值来获取应用私有目录的根目录。从Android4.4开始,读取和写入应用的私有文件不在需要相应的权限。我们可以通过在权限声明中添加maxSdkVersion属性来声明只在较低的版本中请求该权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18"/>
当用户卸载我们的应用时。此目录和里面的内容将会被删除。系统的媒体扫描程序不会扫描该目录里的文件。
注意,在Android4.3及以前的版本。getExternalFilesDir(String type)方法将只提供内部分区的访问权限,应用无法读取或写入sd卡。从Android4.4开始,可以通过getExternalFilesDirs(String type)方法来同时访问两个位置。该方法会返回一个File数组。在数组中的第一个条目会被系统认为主外部存储。Android建议,除非该位置已满或不可使用,否则应该使用该位置。如需兼容Android4.3及以下版本,可通过支持库中的静态方法ContextCompat.getExternalFilesDirs(Context context, String type)。该方法也会返回一个File数组,但是其中仅包含一个条目。
注意,保存在该目录的文件虽然不能被系统的媒体扫描程序所访问,但是其他具有READ_EXTERNAL_STORAGE权限的应用仍可访问上述文件。
我们可以通过getExternalCacheDir()来访问保存到外部存储的缓存文件目录。如果应用被卸载,这些文件也会被删除。与前述 ContextCompat.getExternalFilesDirs()
相似,您也可以通过调用 ContextCompat.getExternalCacheDirs()
来访问辅助外部存储(如果可用)上的缓存目录。