Android数据存储之键值对数据和File数据

来源:互联网 发布:云计算 安全问题 编辑:程序博客网 时间:2024/05/18 05:30

    • Main
    • 存储键值对
      • 获取一个SharedPreferences对象
      • 向SharedPreferences文件写入数据
      • 读取SharedPreferences文件中的数据
    • 存储文件
      • 内部存储和外部存储区域
      • 获得访问外部存储的权限
      • 存储文件到内部存储
      • 存储文件到外部存储
      • 查询可用空间
      • 删除文件

Main

一个APP在使用过程中肯定会产生用户数据,这其中的数据有些需要存储起来。那么Android中如何存储数据呢?

Android中将数据分为了三大类:
1. 键值对数据。比如用户的一些设置,这些数据用SharedPreferences对象来进行存储和修改。
2. File数据。需要将数据存成一个文件,比如用户头像的图片数据。这样的数据和Java中的IO操作相同,再一些Android的特色。
3. 使用数据库。对于一些结构化的数据可以采用数据库来存储,比如联系人信息。

存储键值对

首先要明白使用SharedPreferences对象的方法时发生了什么?SharedPreferences对象指向的是文件系统中的一个文件,文件内容是键值对。这个对象有一些方法可以简便的对这个文件进行插入键值对,编辑键值对,获取键值对数据的操作。

SharedPreferences对象是在对一个文件进行读写操作,这种读写操作被它暴露出来的API简化了过程,不用关注读写的具体实现。

获取一个SharedPreferences对象

获取SharedPreferences有两个方法。
1. getSharedPreferences()
这个方法要传入SharedPreferences对象对应的那个文件的文件名。任何一个context都可以调用这个方法。
2. getPreferences()
这个方法只能Activity调用,访问默认属于这个Activity的SharedPreferences文件。

Context context = getActivity();SharedPreferences sharedPref = context.getSharedPreferences(        getString(R.string.preference_file_key), Context.MODE_PRIVATE);
SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);

上面代码的Context.MODE_PRIVATE代表这个SharedPreferences对象对应的file文件只能由创建它的这个app访问,其它app无法访问。还有MODE_WORLD_READABLEMODE_WORLD_WRITEABLE表示其它App只要知道文件名也是可以访问的。

向SharedPreferences文件写入数据

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);SharedPreferences.Editor editor = sharedPref.edit();editor.putInt(getString(R.string.saved_high_score), newHighScore);editor.commit();

如代码所示,要向一个SharedPreferences文件写入数据,要通过Editor来实现。

读取SharedPreferences文件中的数据

SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);int defaultValue = getResources().getInteger(R.string.saved_high_score_default);long highScore = sharedPref.getInt(getString(R.string.saved_high_score), defaultValue);

如上代码,读取一个SharedPreferences文件的内容是通过一个SharedPreferences对象的getInt()等方法,要传入读取的键值对的键名。还可以传入一个默认值,如果读取失败会返回默认值。


存储文件

Android中的存储文件和在其它系统存储文件是一样的,利用了java.io

内部存储和外部存储区域

Android中存储文件的区域有两个,内部存储(Internal Storage)和外部存储(External Storage)。在Android中要存储文件,必须理解这两个存储区域。

早期的Android的手机存储区域就是手机内存和SD两部分。手机的内存(不是运存)被称为内部存储,SD卡被称为外部存储。

现在许多手机并没有SD卡,而是说内存32G什么的。虽然没有了SD卡,但是系统也将存储划分为了内部存储和外部存储两个区域,内部存储区域用来安装系统和app,外部存储区域一般用来放产生的数据。比如拍的照片,下载的MP3歌曲。
内部存储有以下几个特点:
* 总是可用的
* 存储的数据只有产生数据的app可以访问
* 当app卸载的时候会将这个app在内部存储的所有数据都删除

外部存储的特点:
* 并不总是可用的。可能拔掉了SD卡,或者USB连接到电脑后挂载到电脑上了。
* 存储在外部存储中的数据可以被其它程序访问。
* 当卸载app时只有放在getExternalFilesDir()方法返回的文件目录中的数据会被同时删除。

注意一点,在Android7.0一个app内部储存中私有的数据严格的不能被其它app访问。

app默认是安装到内部储存的,但是如果有需要的话可以在manifest文件中通过指定android:installLocation属性来让app可以安装到外部存储上。

获得访问外部存储的权限

一个App对内部存储默认是有读写权限的,但是对于外部储存的访问是要额外申请权限的。

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

如上所示,分别在manifest文件中给app申请写和读外部存储的权限。值得注意是申请写权限的同时默认了也申请读权限。

当前系统版本默认所有App都有对外部存储的读权限(即使不申请),不过这可能会在以后改变,所以最好还是在app有读外部存储的需求时申请读权限。

存储文件到内部存储

将文件存储到内部存储上,首先要得到一个内部存储区域的文件夹,这样才好存数据。在Android中获取app在内部存储中的存储文件夹有两个方法:getFilesDir()getCacheDir()。顾名思义getFilesDir()会返回一个File对象表示app在内部存储中的一个文件夹。而getCacheDir()返回一个app用来在内部存储上存储缓存的文件夹。

app内部存储文件夹用app的包名来命名,只要将文件夹的一个文件设置为MODE_PRIVATE其它app就不能访问这个文件。

在这两个方法返回的文件夹中创建文件可以用File()方法,如下:

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

或者使用openFileOutput()方法获取一个FileOutputStream在内部存储的文件夹中创建一个文件。如下代码:

String filename = "myfile";String string = "hello world!";FileOutputStream outputStream;try {   outputStream = openFileOutput(filename, context.MODE);   outputSteam.write(string.getBytes());   outputSteam.close();} catch (Exception e){e.printStackTrace();}

与此类似,创建缓存文件就用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) {        //erro handing    }    return file;}

存储文件到外部存储

外部存储除了需要访问权限外,在使用时它还有可能不可用。比如拔掉了SD卡。所以在使用外部存储前要先检查外部存储是否可用。
具体来将通过调用getExternalStorageState()方法,如果返回的状态是MEDIA_MOUNTED代表可以在外部存储读写数据。如下代码:

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()getExternalFilesDir()两个方法。

当app被卸载后放在getExternalStoragePublicDirectory()的文件不会被自动删除。可用通过DIRECTORY_MUSIC或者DIRECTORY_PICTURES参数的方法来制定产生的文件放在app外部存储的哪一个子文件夹中。

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

在外部存储中也可以存储app私有的文件,具体是将文件存储到getExternalFilesDir()返回的File所代表的文件夹中。

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在外部存储上私有文件夹的根文件夹。通过getExternalFilesDir()方法返回的目录在卸载app时也会被删除。

查询可用空间

在存储数据时如果存储空间不够用,那么将会造成许多问题。为了避免这个问题,可以调用getFreeSpace()getTotalSpace()方法来检查下有多少可用的存储空间以及总的存储空间大小是多少。同时不要还有多少空间写沾满它,最好给系统流出10%的存储空间。

如果不能确定要存储的文件有多大,那么可以通过捕获IOException的方式来处理问题。

删除文件

删除一个file最好的方式就是得到这个file的引用后调用delete()方法。
myfile.delete();

如果一个file是存储在内部存储的可以调用deleteFile()方法。
mycontext.deleteFile(filename)

值得注意:在用户卸载app后,这个app在内部存储上产生的文件以及外部存储中存储在getExternalFilesDir()返回的文件夹中的数据都会被删除。

0 0
原创粉丝点击