【Android应用开发技术:文件读写】Android文件系统

来源:互联网 发布:icloud的数据恢复 编辑:程序博客网 时间:2024/06/04 18:11

作者:郭孝星
微博:郭孝星的新浪微博
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
Github:https://github.com/AllenWells

【Android应用开发技术:文件读写】章节列表

一 内部存储和外部存储

所有的Android设备都有两个文件存储区域:”internal” 与 “external” 存储。 那两个名称来自于早先的Android系统中,当时的大多设备都内置了不可变的内存(internal storage),然后再加上一个类似SD card(external storage)这样可以卸载的存储部件。后来有一些设备把”internal” 与 “external” 的部分都做成不可卸载的内置存储了,虽然如此,但是这一整块还是从逻辑上有被划分为”internal”与”external”的。只是现在不再以是否可以卸载来区分了。下面列出了两者的区别:

Internal Storage:

  • 总是可用的
  • 这里的文件默认是只能被你的app所访问的。
  • 当用户卸载App的时候,系统会把internal里面的相关文件都清除干净。
  • Internal是在你想确保不被用户与其他app所访问的最佳存储区域。

External Storage:

  • 并不总是可用的,因为用户有时会通过USB存储模式挂载外部存储器,当取下挂载的这部分后,就无法对其进行访问了。
  • 是大家都可以访问的,因此你可能会失去保存在这里的文件的访问控制权。
  • 当用户卸载你的app时,系统仅仅会删除external根目录(getExternalFilesDir())下的相关文件。
  • External是在你不需要严格的访问权限并且你希望这些文件能够被其他app所共享或者是允许用户通过电脑访问时的最佳存储区域。

尽管App是默认被安装到Internal Storage的,我们还是可以通过在程序的AndroidManifest.xml文件中声明android:installLocation属性来指定程序也可以被安装到External Storage。当某个程序的安装文件很大且用户的internal Storage空间大于external Storage时,用户会倾向与将该程序安装到External Storage。

一 读写权限

对于Internal Storage,我们不需要声明任何权限,因为我们的程序默认就有读写程序目录下的文件的权限。而对于External Storage,我们需要获取相应的权限,获取External Storage写权限的方式如下所示:

<manifest ...>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    ...</manifest>

现在的App都可以在不指定某个专门的权限下做读External Storage的动作。但是,这在以后的版本中会有所改变。如果我们的App只需要读的权限(不是写), 那么我们就需要声明READ_EXTERNAL_STORAGE权限。

<manifest ...>    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />    ...</manifest>

二 文件读写

2.1 internal storage文件读写

当保存文件到internal storage时,你可以通过执行下面两个方法之一来获取合适的目录作为 FILE 的对象:

  • getFilesDir() : 返回一个File,代表了你的app的internal目录。
  • getCacheDir() : 返回一个File,代表了你的app的internal缓存目录。请确保这个目录下的文件在一旦不再需要的时候能够马上被删除,并对其大小进行合理限制,例如1MB 。如果系统的内部存储空间不够,会自行选择删除缓存文件。

获取到目录后,我们可以在该目录创建文件,如下所示:

File file = new File(context.getFilesDir(), filename);

我们也可以执行openFileOutput()来获取一个FileOutputStream用于写文件到Internal目录,如下所示:

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中抽取了一个文件名,然后再在程序的internal缓存目录下创建了一个以这个文件名命名的文件。   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;}

我们的App在Internal Storage目录是以App的包名作为标识存放在Android文件系统的特定目录下,如下所示:

data/data/<package_name>

如果我们设置文件为可读的,而且App需要知道我们的包名与文件名,那么它们就可以读取我们的Internal文件。这种情况下我们可以使用MODE_PRIVATE来禁止其他App的读写。

2.1 External storage文件读写

因为external storage可能是不可用的,比如遇到SD卡被拔出等情况时。因此你应该在访问之前去检查其是否可用。我们可以通过执行getExternalStorageState()来查询external storage的状态。如果返回的状态是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;}

External Storage对于用户与其他App是可修改的,App存储到External Storage可能有两种类型,如下所示:

  • 公有文件:这些文件对与用户与其他App来说是公有的,当用户卸载我们的App时,这些文件应该保留。比如,那些被我们的App拍摄的图片或者下载的文件。
  • 私有文件:这些文件是被我们App所拥有的,它们应该在我们的App被卸载时删除掉。尽管由于存储在External Storage,那些文件从技术上而言可以被用户与其他App所访问,但实际上那些文件对于其他app是没有意义的。因此,当用户卸载我们的App时,系统会删除我们的App的private目录。比如,那些我们的App下载的缓存文件。

如果我们想要保存文件为public形式的,可以使用getExternalStoragePublicDirectory()方法来获取一个File对象来表示存储在External Storage的目录。这个方法会需要你带有一个特定的参数来指定这些public的文件类型,以便于与其他public文件进行分类。参数类型包括DIRECTORY_MUSIC 或者 DIRECTORY_PICTURES. 如下所示:

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()来获取相应的目录,并且传递一个指示文件类型的参数。每一个以这种方式创建的目录都会被添加到External Storage封装你的app目录下的参数文件夹下(如下则是albumName)。这下面的文件会在用户卸载你的App时被系统删除。如下所示:

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;}

如果刚开始的时候,没有预定义的子目录存放你的文件,你可以在 getExternalFilesDir()方法中传递 null . 它会返回App在External Storage下的private的根目录。
getExternalFilesDir() 方法会创建的目录会在App被卸载时被系统删除。如果文件在App被删除时仍然保留,应使用getExternalStoragePublicDirectory()。

注意:不管是使用getExternalStoragePublicDirectory()来存储可以共享的文件,还是使用getExternalFilesDir() 来储存那些对App来说是私有的文件。都要使用那些类似DIRECTORY_PICTURES的API的常量。那些目录类型参数可以确保那些文件被系统正确的对待。例如,那些以 DIRECTORY_RINGTONES 类型保存的文件就会被系统的Media Scanner认为是ringtone而不是音乐。

另外提一点就是我们在写入文件之前,有时候需要查询存储的剩余空间。如果我们事先知道想要保存的文件大小,可以通过执行getFreeSpace()或者getTotalSpace()来判断是否有足够的空间
来保存文件,从而避免发生IOException。那些方法提供了当前可用的空间还有存储系统的总容量。

然而,系统并不能保证你可以写入通过getFreeSpace()查询到的容量文件,如果查询的剩余容量比要写入的文件大小多几MB,或者说文件系统使用率还不足90%,这样则可以继续进行写的操作,否则最好不要写进去。

写文件之前,并非一定有要去检查剩余容量。我们可以尝试先做写的动作,然后通过捕获IOException来分析容量是否不足。这种做法仅适合于事先不知道你想要写的文件的确切大小的情况。例如,如果在把PNG图片转换成JPEG之前,你并不知道最终生成的图片大小是多少。

三 文件删除

删除文件最直接的方法是直接执行文件的delete()方法,如下所示:

myFile.delete();

如果文件是保存在internal storage,我们可以通过Context来访问并通过执行deleteFile()进行删除,如下所示:

myContext.deleteFile(fileName);

当App被卸载时,Android系统会删除以下文件:

  • 所有保存到internal storage的文件。
  • 所有使用getExternalFilesDir()方式保存在external storage的文件。

除此之外,我们应该手动删除所有通过getCacheDir()方式创建的缓存文件,以及那些不会再用到的文件。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 失业金汇到保险金账户怎么办 氧气罐阀门漏气怎么办 小微餐饮证怎么办 打网球手腕疼怎么办 晚上睡觉饿了怎么办 孕妇凌晨饿了怎么办 减肥想吃泡面怎么办 自考的实践考核怎么办 c1本怎么办从业资格证 办理资格证假的怎么办 高一学习差怎么办 职业资格证书理论考试不合格怎么办 职称证查不到怎么办 社保与工资不符怎么办 社保审计不过关怎么办 企安宝登录不上怎么办 苹果维修没发票怎么办 园林绿化资质取消后怎么办 出租车从业资格证到期怎么办 养老金认证身份证不符怎么办 硬盘指示灯不亮怎么办 做业务产品质量很差怎么办 没有户籍证明了怎么办 回执编号忘了怎么办 泳镜里面花了怎么办 网页打印预览空白怎么办 中专毕业证掉了怎么办 会计证年检忘了怎么办 会计准考证丢了怎么办 从业资格证没带怎么办 安全证过期了怎么办 安全员证掉了怎么办 局部抗浮不满足怎么办 职称代评被骗怎么办 租到了公租房怎么办 公租房不住了怎么办 公寓不退押金怎么办 找物业租房被骗怎么办 租房子被骗了怎么办 公租房怎么办入住手续 重庆公租房摇到号怎么办