将数据保存为文件

2016-06-28 · 🙈Lei · 0条 · 447次

File对象适合按照从开始到结束的顺序不跳过地读取或者写入大量数据。例如:它适合图像文件或通过网络交换的任何内容。

>_ 内部存储 外部存储

在Android早期,大多数设备都提供内置的非易失性内存(内部存储),以及移动存储介质,比如微型SD卡(外部存储)。一些设备将永久性存储空间划分为“内部”和“外部”分区,即便没有移动存储介质,也始终有两个存储空间,并且无论外部存储设备是否可移动,API的行为均一致。

>_ 权限

1.要向外部存储写入信息,需要“写”的权限。

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

读取外部存储,需要“读”的权限。如果使用了“写”权限,则默认拥有“读”的权限。

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

2.您无需任何权限,即可在内部存储中保存文件,始终具有在内部存储中进行读写的权限。

>_ 存入内部存储

1.可以利用getFilesDir()和getCacheDir()两个方法之一来获取作为File的相应目录。

(1).getFilesDir()

返回表示您的应用的内部目录的File。

(2).getCacheDir()

返回表示您的应用临时缓存文件的内部目录的File。务必删除所有不再需要的文件并对在指定时间您使用的内存量实现合理大小的限制,比如1MB。吐过在系统即将耗尽存储,它会在不进行警告的情况下删除您的缓存文件。

2.在这些目录中创建文件:

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

3.写入文件:openFileOutput()

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

4.缓存文件createTempFile()

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

注意: 您的应用的内部存储设备目录由您的应用在Android 文件系统特定位置中的软件包名称指定。在技术上,如果您将文件模式设置为可读,另一个应用可以读取您的内部文件。 但是,另一个应用也需要知道您的应用的软件包名称和文件名。 其他应用无法浏览您的内部目录并且没有读写权限,除非您明确将文件设置为可读或可写。 只要您为内部存储上的文件使用 MODE_PRIVATE, 其他应用便从不会访问它们。

>_ 存入外部存储

1.外部存储可能不可用,例如当用户已将存储装载到电脑或已移除提供外部存储的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;
}

2.外部存储的两种类型

(1)公共文件

供其它应用和用户自由使用的文件。当用户卸载掉应用后,用户仍然可以使用这些文件。

(2)私有文件

属于您的应用且应在用户卸载您的应用时删除的文件。尽管这些文件在技术上可被用户和其他应用访问,实际上却不向您的应用之外的用户提供值。当用户卸载应用的时候,会被删除。

3.使用公共文件

使用getExternalStoragePublicDirectory()方法获取表示外部存储上相应目录的File。该方法需要指定文件类型,如 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;
}

4.使用私有文件

可以使用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;
}

如果没有适合您文件的预定义子目录名称,可以改为调用getExternalFilesDir(),传递null。这将返回外部存储上您应用的专用目录的根目录。

注意:无论是创建公共文件还是私有文件,使用诸如DIRECTORY_PICTURES的API常数提供的目录名称是非常重要的,这些目录名称可以确保系统正确处理这些文件。

>_ 查询可用空间

如果事先知道将保存的数据量,可以查出是否有足够的可用空间,则无需调用getFreeSpace()【目前的可用空间】或getTotalSpace()【存储卷中的总空间】。可以用来避免填充存储卷以致超出特定阈值。

系统并不能保证可以写入与getFreeSpace()指示的一样多的字节。如果返回的数字比您要保存的数据大小大出几M,或如果文件系统所占空间不到90%,则可安全操作,否则,可能不应写入存储。

注意:保存您的文件之前,您无需检查可用空间量。 您可以尝试立刻写入文件,然后在 IOException 出现时将其捕获。 如果您不知道所需的确切空间量,您可能需要这样做。 例如,如果在保存文件之前通过将 PNG 图像转换成JPEG 更改了文件的编码,您事先将不知道文件的大小。

>_ 删除文件

1.应该始终删除不再需要的文件。删除文件最直接的方式就是直接调用delete()。

myFile.delete();

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

myContext.deleteFile(fileName);

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

  • 您保存在内部存储中的所有文件
  • 您使用 getExternalFilesDir() 保存在外部存储中的所有文件。

但是,您应手动删除使用 getCacheDir() 定期创建的所有缓存文件并且定期删除不再需要的其他文件。


  0