Android使用文件系统来读取和保存文件的, 相关的包请参照java.io包下面的文件。
1) 选择内部存储(Internal Storage)或者是外部存储(External Storage)
Android设备有两个存储区域:内部存储和外部存储空间, 顾名思义, 内部存储是跟随android系统的, 外部系统是可拆卸的设备例如SD card等。
对于很多Android设备, 即使没有前面所说的外部设备(如SD card), 系统同样提供在内部存储区域上提供了一块空间作为"外部存储"。因此即使
没有可拆卸的外设,仍然后两套存储空间可供选择。API对两种外部设备是同样适用的。 下面是两种存储空间的一些特性:
a. 内部设备(Internal Storage)
1. 内部设备是一直存在的,并且是一直有效。
2. 默认情况下,存储在内部设备上的文件只能被自己的app单独访问。
3. 当卸载app的时候,系统会移除所有的保存在内部设备上的app文件。
由以上特点可以看出, 内部设备适合保存那些只有自己的app访问的数据和文件。 比如登录后的用户信息, 数据库文件等私密信息。
b. 外部设备(External Storage)
1. 外部设备并不保证是一直存在且有效的。比如user可能挂载了外部设备然后移除了它。
2. 外部设备是"公共区域", 存储在外部设备上的文件无法控制其私密性,其他app可以读取操作它。
3. 当卸载app的时候,系统只会移除存储在getExternalFilesDir()文件夹下的文件,其他的文件不会主动移除。 也就是说,会产生垃圾数据。
对比内部设备, 可以看出外部设备适合存储那些不需要阅读权限的文件。
2) 获取读写权限。
为了读取外部设备,需要在manifest中添加读写权限:
<manifest ...>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
...
</manifest>
值得注意的是, 现在所有的app均有能力读取外部设备,并不需要特殊的读权限。 但是在未来的Android版本中,会加入更多的限制。
因此在你的app中,同样需要添加读权限已防备未来更新版本带来的麻烦。
<manifest ...>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...
</manifest>
而读写内部设备不需要任何权限。 app拥有读写它的内部存储空间的权利。
3) 存储文件到内部设备
当需要存储文件到内部空间时,可以通过File类的两种方法来获取存储路径
getFilesDir() 会返回你的app的内部存储空间的路径
getCacheDir() 返回你的app的内部存储空间的缓存目录, 如果缓存文件不太需要的话,请及时清理已保证缓存目录的以保证缓存文件不会占用太大空间,
比如1M, 不然系统有可能在没有警告的情况下直接删除缓存目录下的文件。
如果要在背部设备上创建文件,可以使用如下代码:
File file = new File(context.getFilesDir(), filename);
相应的,可以使用openFileOutput() 来获取FileOutputStream , 然后通过它来写文件到内部设备。下面是例子:
String filename = "myfile"; String string = "Hello world!"; FileOutputStream outputStream; try { outputStream = openFileOutput(filename, Context.MODE_PRIVATE); outputStream.write(string.getBytes()); outputStream.close(); } catch (Exception e) { e.printStackTrace(); }
或者是,你同样可以使用createTempFile()来创建文件, 下面的例子是通过url获取文件名,然后保存在缓存目录下:
public File getTempFile(Context context, String url) { File file; try { String fileName = Uri.parse(url).getLastPathSegment(); file = File.createTempFile(fileName, null, context.getCacheDir()); catch (IOException e) { // Error while creating file } return file; }
内部设备的目录是以你的包名存储的, 从技术上来说, 如果你把文件保存成readble模式,其他的app可以读取此文件,当然它要知道
你的包名和你的文件名。其他的app不能浏览你的内部文件夹, 如果你没有把文件属性设置为readable或者writable。
只要你使用MODE_PRIVATE模式,其他的app就不能访问你的文件。
4) 外部存储空间
因为外部空间是可拆卸的,因此在访问它之前,必须确保其存在。 Android提供了响应的接口来判断外设是否可用。当外设的状态为MEDIA_MOUNTED,即意味着外设可读写。
下面的代码可以用来检查外设是否可用
/* Checks if external storage is available for read and write */ public boolean isExternalStorageWritable() { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state)) { return true; } return false; } /* Checks if external storage is available to at least read */ public boolean isExternalStorageReadable() { String state = Environment.getExternalStorageState(); if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) { return true; } return false; }
前面也提到过,外设上的文件也有区别, 有的随着app的卸载会被系统同时删除,有些目下的文件不会同时被删除。
因此, 根据你的文件的类型,你可以选择将他们保存在不同的目录下:
共有文件:
这些文件可同时被其他的app使用,当卸载时,不希望被删除,比如下载的图片,或者使用app拍摄的照片等。
私有文件:
你的app的单独使用的文件,在卸载时,希望同时被删除,尽管这些文件能够被其他的app访问,但对用户已经没有价值。例如一些缓存数据。
当你保存共有文件时,可以使用getExternalStoragePublicDirectory()方法来获取外设的根目录,在此根目录上创建新的文件路径。
这个方法需要指定你需要存储的类型,比如图片或者音乐等。例如:
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(), 同样可以指定需要的类型, 例子如下:
public File getAlbumStorageDir(Context context, String albumName) { // Get the directory for the app's private pictures directory. File file = new File(context.getExternalFilesDir( Environment.DIRECTORY_PICTURES), albumName); if (!file.mkdirs()) { Log.e(LOG_TAG, "Directory not created"); } return file; }
如果不需要指定类型,可以传递null到getExternalFilesDir()中,它返回的是您的应用程序的在外部存储的根目录。
记住两者之间的区别。
5) 查询剩余空间
如果你知道需要保存的文件的大小,你需要保证有足够的空间来存储这些文件。
可以通过getFreeSpace() 或者 getTotalSpace() 来获取文件的大小。
6) 删除文件:
可以通过File的delete()方法来删除文件。或者通过context.deteleFile(fileName)来删除内部空间的文件。
版权声明:本文为博主原创文章,未经博主允许不得转载。