Android文件存储

File对象适合顺序不跳过地读取和写入大量数据。例如,图片文件或通过网络交换的任何内容。

存储区域

Android设备有两个文件存储区域:“内部”和“外部”存储。早期设备“内部存储”指的是内置存储,而“外部存储”指的是外置可拆卸的移动存储,比如SD卡。现在基本上没有外置移动存储,而依然将存储区域划分为这两部分。

内部存储

  • 始终可用
  • 只有你的应用可以访问这里保存的文件
  • 用户卸载应用时候,会删除应用在这里存放的文件

不希望用户或其他应用访问的那些文件信息,可以放到这里。

外部存储

  • 并非始终可用。用户可采用USB存储设备的形式装载外部存储,并且可拆卸
  • 全局可读。因此这里存放的文件可以不受你的控制被读取。
  • 当用户卸载应用时候,系统会卸载你存放在通过调用getExternalFilesDir()获取的目录里的文件。

外部存储适用于存放那些无需访问限制,以及你希望共享给其他应用或允许用户使用电脑访问的文件。

应用默认安装在内部存储中,可以修改应用清单文件中的android:installLocation属性来指定默认安装位置。

获取访问外部存储的权限

当前应用默认具有外部存储读取权限,而写权限必须申请。后续版本可能会要求申请外部存储区域读权限。

获取外部存储写权限,隐含外部区域读权限,反之不成立。

获取写权限

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

获取读权限

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

应用始终具有读写内部存储区域的权限,无需申请。

保存文件到内部存储

内部应用存储空间根目录通常是/data/data/<package-name>/

获取缓存目录的方法(Context类提供):

  • getFilesDir():返回应用内部存放文件的目录的绝对路径。一般就是/data/data/<package-name>/files。这个目录也是调用openFileOutput方法创建的文件的目录。
  • getCacheDir():返回应用内部存储的临时目录。通常是/data/data/<package-name>/cache。当系统内部存储即将耗尽的时候,可能会删除这个目录下的文件。
  • getDir():方法getDir(String name, int mode)包含两个参数,可用于在应用内部存储根目录下创建或打开自定义的文件目录。name表示自定义的文件目录名。mode表示操作模式,用来控制该目录的读写权限,默认为MODE_PRIVATE,表示仅仅应用自身可以访问。MODE_WORLD_READABLE允许其他应用读取你创建的文件,不安全,已经不建议使用。MODE_WORLD_WRITEABLE允许其他应用读写你的文件,不安全,不建议使用。

在目录下创建文件,File的构造参数中传入目录和文件名,例如

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

或者,调用openFileOutput()方法获取写入到getFilesDir()目录的FileOutputStream。比如,在getFilesDir()目录下写入一个名为myfile.txt的文件,内容为Hello world!

String filename = "myfile.txt";
String string = "Hello world!";
FileOutputStream outputStream;

try {
  outputStream = openFileOutput(filename, Context.MODE_PRIVATE);
  outputStream.write(string.getBytes());
  outputStream.close();
} catch (Exception e) {
  e.printStackTrace();
}

保存文件到外部存储

外部存储可能不可用,比如用户将其挂载到了电脑或者移除了提供外部存储的SD卡,因此,在访问之前,需要先确认其可用。

调用getExternalStorageState()方法查询外部存储状态,如果返回为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;
}

虽然外部存储可被用户和其他应用进行修改,但你仍然可以在这里保存两类文件:

  • 公共文件。可供其他应用和用户自由使用的文件。应用被卸载后,用户仍然可以使用。比如当前应用拍摄的照片或其他已下载的文件。
  • 私有文件。属于应用私有文件,在应用被卸载时候,系统可以删除应用外部私有目录的所有文件。技术上可以被用户或其他应用访问,但实际上被访问也没关系的文件。

公共文件目录获取

公共文件目录可以通过getExternalStoragePublicDirectory()方法获取,需要指定文件类型参数,以便外部统一处理。比如DIRECTORY_MUSICDIRECTORY_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()方法传入目录名字获取相应目录。当用户卸载应用时候,系统会删除这些文件。

比如,使用下面方法创建个人相册目录:

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

上述方法会在Environment.DIRECTORY_PICTURES目录下创建albumName值的目录,当然你也可以将第一个参数传为null,则会在你应用外部存储私有目录的根目录下创建。

查询可用空间

File类的getFreeSpace()getTotalSpace()返回当前目录下可用空间和总的空间大小。

但是,系统并不保证你能够写入getFreeSpace()大小的数据。如果可用空间大小比你要保存的数据多几MB,或者文件系统剩余空间大小超过10%,你多半是可以安全写入。否则的话,你可能不应该写入存储。

写入之前也可以不检查磁盘可用量,可以尝试写入,然后在IOException发生时捕获。

删除文件

记住,文件不用了就及早删除。删除文件的方法:

File.delete()

如果文件保存在内部存储中,还可以调用Context.deleteFile(fileName)来定位和删除文件。

注:当用户卸载您的应用时,Android 系统会删除以下各项:

  • 保存在内部存储中的所有文件
  • 使用getExternalFilesDir()保存在外部存储中的所有文件。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 保存文件 Android 使用与其他平台上基于磁盘的文件系统类似的文件系统。 本课程讲述如何使用 Android ...
    李建彪阅读 4,865评论 0 2
  • 引言:文件存储[内部存储]和[外部存储]。SD 卡上的文件路径。时间:2017年06月17日作者:JustDo23...
    JustDo23阅读 4,247评论 0 4
  • 在Android中我们大多数情况下我们用的都是绝对路径; 文件存储位置说明: 内部存储不是内存,内部存储位于系统中...
    沈凤德阅读 10,782评论 1 2
  • 一直一来没有认真关注过android 的文件存储,现在做一个总结,我认为有用的,网上的博客真是写的叫一个渣渣,根本...
    子丿龙阅读 2,981评论 0 0
  • 随着网络技术的发展,网络游戏开始迅速风靡全球。无论是大人还是小孩,甚至是老人都对网络游戏产生了极大的兴趣。 游戏本...
    牛蓓阅读 3,060评论 0 0

友情链接更多精彩内容