Android文件存储

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

存储区域

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

内部存储

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

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

外部存储

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

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

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

获取访问外部存储的权限

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

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

获取写权限


    
    ...

获取读权限


    
    ...

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

保存文件到内部存储

内部应用存储空间根目录通常是/data/data//

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

  • getFilesDir():返回应用内部存放文件的目录的绝对路径。一般就是/data/data//files。这个目录也是调用openFileOutput方法创建的文件的目录。
  • getCacheDir():返回应用内部存储的临时目录。通常是/data/data//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()保存在外部存储中的所有文件。

你可能感兴趣的:(Android文件存储)