Android数据存储及常见操作



一、引言

不管是什么平台,我觉得数据存储都是其中的重点之一,对数据的存储是否有着良好的技术支持,是一个好的开发平台的体现。数据,特别是如今的数据大时代,谁拥有数据,谁就能掌握未来,所以在Android中数据对我们是多么重要。

Android平台中,涉及数据存储的有几个,但主要的有三种:

  • 文件存储
  • SharedPreference存储
  • SQLite数据库存储

二、文件存储

文件存储是Android中最基本的一种存储方式,和Java中实现I/O的方式一样,由Context类提供openFileInput()和openFileOutput()方法打开。文件存储主要分两种存储:

  • 一种是内部存储,使用了FileInputStream类中的openFileInput()方法,用于读取数据;使用了FileOutputStream类中的openFileOutput()方法,用于写入数据
  • 一种是外部存储,使用Enviroment类中的getExternalStorageDirectory()方法对外部存储上的文件进行读写

2.1 内部存储

内部存储的写入文件步骤:

  • 获取文件输出流对象 FileOutputStream
  • 使用FileOutputStream类的openFileOutput(String name, int mode)方法
  • 调用FileOutputStream对象的write()方法写入文件
  • 调用flush()方法,因为write()方法是写入缓冲区的,调用flush()方法将缓冲中的数据写入到文件,清空缓存
  • close()方法用于关闭FileOutputStream

代码示例:

    FileOutputStream outStream = this.openFileOutput("MadDog.txt", Context.MODE_PRIVATE);
    outStream.write("xmamiga".getBytes());
    outStream.close();

openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。创建的文件保存在/data/data/ <package name>/files目录下。

内部存储的读取文件步骤:

  • 获取文件输入流对象 FileInputStream
  • 使用FileInputStream类的openFileInput()方法来实现
  • 调用FileInputStream对象的read()方法
  • 调用close()关闭文件输入流对象

代码示例:

    File file = new File("/data/data/cn.itcast.action/files/itcast.txt");
    FileInputStream inStream = new FileInputStream(file);
    Log.i("FileTest", readInStream(inStream));

Activity还提供了getCacheDir()和getFilesDir()方法:

  • getCacheDir()方法用于获取/data/data/<package name>/cache目录
  • getFilesDir()方法用于获取/data/data/<package name>/files目录

在程序中访问SDCard,需要先申请访问SDCard的权限。在AndroidManifest.xml中加入访问SDCard的权限如下:

<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

综上,在Android中读取与写入文件的方法,和Java中实现I/O的程序是一样的,提供了openFileInput()和openFileOutput()方法来读取设备上的文件。通过Context.openFileOutput()获取输出流,参数分别为文件名和存储模式;通过Context.openFileInput()获取输入流,参数为文件名。

2.2 外部存储

外部存储才是我们平时操作最多的,外部存储一般就是我们上面看到的storage文件夹,当然也有可能是mnt文件夹,这个不同手机厂家有可能不一样。一般来说,在storage文件夹中有一个sdcard文件夹,这个文件夹中的文件又分为两类,一类是公有目录,还有一类是私有目录,其中的公有目录有九大类,比如DCIM、DOWNLOAD等这种系统为我们创建的文件夹,私有目录就是Android这个文件夹,这个文件夹打开之后里边有一个data文件夹,打开这个data文件夹,里边有许多包名组成的文件夹。

读写数据代码示例:

    if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
        File sdCardDir = Environment.getExternalStorageDirectory();//获取SDCard目录  "/sdcard"
        File saveFile = new File(sdCardDir,"MadDog.txt");

        //写数据
        try {
            FileOutputStream fos= new FileOutputStream(saveFile);
            fos.write("xmamiga".getBytes());
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //读数据
        try {
            FileInputStream fis= new FileInputStream(saveFile);
            int len =0;
            byte[] buf = new byte[1024];
            StringBuffer sb = new StringBuffer();
            while((len=fis.read(buf))!=-1){
                sb.append(new String(buf, 0, len));
            }
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

使用sdcard存储的数据,不限制只有本应用访问,任何可以有访问Sdcard权限的应用均可以访问,而Sdcard相对于设备的内部存储空间而言,会大很多,所以一般比较大的数据,均会存放在外部存储中。

三、SharedPreferences存储

Android平台给开发者提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。使用SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在/data/data/<package name>/shared_prefs目录。SharedPreferences是一种数据存储方式,用来存储一些简单的信息,位于android.content包中,以键值对的模式进行存储,键值对(key-value)。对于存储的基本信息,如int,string,boolean,float和long。

  • 使用getSharedPreferences()方法获取
  • 使用getPreferences()方法获取

两个方法的区别在于:如果使用getSharedPreferences()方法,则保存的数据是全局性的,即在整个app应用过程中都是可获取的。当使用此方法时,系统会在/data/data/包名/shared_prefs目录下生成一个xxx.xml文件,文件名根据getSharedPreferences()传入的第一个参数而定;而使用getPreferences()方法,所保存的数据仅对保存数据的那个Activity有效,而在其他Activity中将无法获取。系统会在/data/data/包名/shared_prefs目录下生成一个Activity名.xml的文件。

实现SharedPreferences存储步骤:

  • 调用SharedPreferences类的edit()方法,获取SharedPreferences.Editor对象
  • 调用一个SharedPreferences.Editor对象的putXXX()的方法获取数据
  • 使用commit()方法提交数据

示例代码如下:

    SharedPreferences sharedPreferences = getSharedPreferences("xmamiga", Context.MODE_PRIVATE);
    Editor editor = sharedPreferences.edit();//获取编辑器
    editor.putString("name", "dog");
    editor.putInt("age", 4);
    editor.commit();//提交修改

Activity还提供了另一个getPreferences(mode)方法操作SharedPreferences,这个方法默认使用当前类不带包名的类名作为文件的名称。

在需要获取数据的地方,使用SharedPreferences对象的getBoolean()(或者getString()、getInt()等,同样由所保存的数据的数据类型而定)等方法读取值。访问SharedPreferences中的数据代码如下:

SharedPreferences sharedPreferences = getSharedPreferences("xmamiga", Context.MODE_PRIVATE);
//getString()第二个参数为缺省值,如果preference中不存在该key,将返回缺省值
String name = sharedPreferences.getString("name", "");
int age = sharedPreferences.getInt("age", 1);

四、SQLite数据库存储

SQLite是一款轻量级的关系型数据库,它的运算很快,占用空间小,SQLite不仅有SQL语法支持,独立,还有数据库的ACID事务,SQLite数据库为一种嵌入式数据库。涉及到重要的类:访问数据的类---SQLiteOpenHelper

五个重要的方法:

  • getReadableDatabase()---对数据库进行查询
  • getWritableDatabase()---对数据库进行修改等等
  • onCreate(SQLiteDatabase db)---创建数据库
  • onOpen(SQLiteDatabase db)---打开数据库
  • onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)---更新数据库

SQLiteOpenHelper类,它是SQLiteDatabase的帮助类,用于管理数据库的创建和升级,SQLiteOpenHelper类为抽象类,有两个要重写的方法:onCreate()和onUpgrade(),用于去实现创建和升级数据库。
在SQLiteOpenHelper类中还需要一个构造方法,这个方法接收四个参数,分别为Context context,String name, CursorFactory factory,int version这四个。第一个是参数context,第二个是数据库名,第三个是自定义Cursor,一般为null,第四个为当前的数据库版本号。
在SQLiteOpenHelper类中有两个重要的实例方法,为getReadableDatabase()和getWritableDatabase()这两个方法。调用这其中的方法就能够创建数据库了。如果存在数据库就打开,没有就创建。
SQLiteOpenHelper类是一个SQLite帮助类,实现SQLite的数据操作,创建一个类去继承SQLiteOpenHelper,当访问数据库SQLite时必须使用SQLiteOpenHelper类

public class MySQLiteOpenHelper extends SQLiteOpenHelper {

    private static final String DB_NAME = "user.db";
    private static final int VERSION = 1;

    public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        //name:数据库名称,version:数据库版本,factory:游标工厂
    }

    public MySQLiteOpenHelper(Context context) {
        super(context, DB_NAME, null, VERSION);
    }
    //数据库创建
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table person (_id integer primary key autoincrement, " +
                "name char(10), phone char(20), money integer(20))");
    }
    //数据库升级
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

    @Override
    public void onOpen(SQLiteDatabase db) {
        super.onOpen(db);
    }
}

常用的一些方法:

方法 说明
execSQL() 执行SQL语句实现增删操作
Cursor rawQuery() 执行sql语句查询数据库
insert() 往数据库插入数据
delete() 从数据库删除数据
update() 更新数据库
query() 查询数据
beginTransaction() 开始事务
setTransactionSuccessful() 设置事务成功
endTransaction() 结束事务

五、总结

这三种存储方式还可以结合用,我们使用SharedPreferences来存储用户配置文件,当用户启动程序时,更新配置。使用File来存储大型数据文件,比分说音频文件,视频文件等。使用Sqlite来存储用户数据,一个对象的属性数值。