Android将数据存储在内存中分为内部存储和外部存储。
下面看看官方对内部存储和外部存储特定的介绍。
内部存储:
它始终可用。
只有您的应用可以访问此处保存的文件。
当用户卸载您的应用时,系统会从内部存储中移除您的应用的所有文件。
当您希望确保用户或其他应用均无法访问您的文件时,内部存储是最佳选择。
外部存储:
它并非始终可用,因为用户可采用 USB 存储设备的形式装载外部存储,并在某些情况下会从设备中将其移除。
它是全局可读的,因此此处保存的文件可能不受您控制地被读取。
当用户卸载您的应用时,只有在您通过getExternalFilesDir() 将您的应用的文件保存在目录中时,系统才会从此处移除您的应用的文件。
对于无需访问限制以及您希望与其他应用共享或允许用户使用计算机访问的文件,外部存储是最佳位置。
要存储数据首先要给程序添加权限,与数据存储有关的权限有两个。
写入权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
读取权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
如果添加了写入权限则默认包含了读取权限,不必在添加读取权限。
首先来看内部存储的具体操作:
使用getFilesDir()在内部存储中创建新文件
File file = new File(context.getFilesDir(), filename);
使用FileOutputStream,FileInputStream对创建的文件进行读写
final String filename = file.getName();
String string = "Hello world!";
FileOutputStream outputStream;
try {
outputStream = openFileOutput(filename, MODE_PRIVATE);
outputStream.write(string.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
FileInputStream fileInputStream = openFileInput(filename);
StringBuffer m = new StringBuffer();
byte[] bytes = new byte[1024];
try {
while (fileInputStream.read(bytes) != -1) {
String str = new String(bytes);
m.append(str);
}
Log.d("tag", "content = " + m);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
使用getCacheDir()创建内部存储缓存文件
下面是一个使用Url地址创建缓存文件的例子,由于createTempFile()第二个参数未null,缓存文件后缀命为.tmp
public File getTempFile(Context context, String url) {
File file = null;
try {
String fileName = Uri.parse(url).getLastPathSegment();
Log.d("tag", "fileName = " + fileName);
file = File.createTempFile(fileName, null, context.getCacheDir());
} catch (IOException e) {
// Error while creating file
}
return file;
}
外部存储的具体操作:
在进行外部存储具体操作之前,我们应先检查外部存储的状态
使用Environment.getExternalStorageState()方法得到外部存储的状态。
检查外部存储是否能够读写的方法:
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
检查外部存储是否能够写入的方法:
public boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
return true;
}
return false;
}
为了统一管理存储路径,Android将外部存储划分为公共文件和私有文件。
公共文件
应供其他应用和用户自由使用的文件。 当用户卸载您的应用时,用户应仍可以使用这些文件。
例如,您的应用拍摄的照片或其他已下载的文件。私有文件
属于您的应用且在用户卸载您的应用时应予删除的文件。 尽管这些文件在技术上可被用户和其他应用访问(因为它们存储在外部存储中), 但它们实际上不向您的应用之外的用户提供任何输出值。 当用户卸载您的应用时,系统会删除应用外部私有目录中的所有文件。
例如,您的应用下载的其他资源或临时介质文件。
使用 Environment.getExternalStoragePublicDirectory() 方法获取表示外部存储设备上公共文件相应目录的 File
使用 context.getExternalFilesDir() 方法获取表示外部存储设备上私有文件相应目录的 File
下面是官方API在共享存储上操作图片的典型代码示例:
void createExternalStoragePublicPicture() {
// Create a path where we will place our picture in the user's
// public pictures directory. Note that you should be careful about
// what you place here, since the user often manages these files. For
// pictures and other media owned by the application, consider
// Context.getExternalMediaDir().
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
try {
// Make sure the Pictures directory exists.
path.mkdirs();
// Very simple code to copy a picture from the application's
// resource into the external file. Note that this code does
// no error checking, and assumes the picture is small (does not
// try to copy it in chunks). Note that if external storage is
// not currently mounted this will silently fail.
InputStream is = getResources().openRawResource(R.drawable.balloons);
OutputStream os = new FileOutputStream(file);
byte[] data = new byte[is.available()];
is.read(data);
os.write(data);
is.close();
os.close();
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this,
new String[] { file.toString() }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
Log.i("ExternalStorage", "Scanned " + path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
}
});
} catch (IOException e) {
// Unable to create file, likely because external storage is
// not currently mounted.
Log.w("ExternalStorage", "Error writing " + file, e);
}
}
void deleteExternalStoragePublicPicture() {
// Create a path where we will place our picture in the user's
// public pictures directory and delete the file. If external
// storage is not currently mounted this will fail.
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
file.delete();
}
boolean hasExternalStoragePublicPicture() {
// Create a path where we will place our picture in the user's
// public pictures directory and check if the file exists. If
// external storage is not currently mounted this will think the
// picture doesn't exist.
File path = Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES);
File file = new File(path, "DemoPicture.jpg");
return file.exists();
}
私有文件API的使用与共享文件类似,当getExternalFilesDir() 的参数为 null时。这将返回外部存储上您的应用的专用目录的根目录。