Android基础教程:数据存储方式

Arthur 2011-10-18

无论是神马平台,神马开发环境,神马软件程序,数据都是核心。对于开发平台来讲,如果对数据的存储有良好的支持,那么对应用程序的开发将会有很大的促进作用。

总体的来讲,数据存储方式有三种:一个是文件,一个是数据库,另一个则是网络。其中文件和数据库可能用的稍多一些,文件用起来较为方便,程序可以自己定义格式;数据库用起稍烦锁一些,但它有它的优点,比如在海量数据时性能优越,有查询功能,可以加密,可以加锁,可以跨应用,跨平台等等;网络,则用于比较重要的事情,比如科研,勘探,航空等实时采集到的数据需要马上通过网络传输到数据处理中心进行存储并进行处理。

对于Android平台来讲,它的存储方式也不外乎这几种,按方式总体来分,也是文件,数据库和网络。但从开发者的角度来讲它可以分为以下五种方式:

  1. SharedPreferences共享偏好
  2. Internal Storage内部存储空间
  3. External Storage外部存储空间
  4. SQLite Database数据库
  5. Internet网络
这几种方式各自有各自的优点和缺点,要根据不同的实际情况来选择,而无法给出统一的标准。下面就各种方式谈谈它们的优缺点,以及最合适的使用情况:

  1. Shared Preferences共享偏好
SharedPreferences是用来存储一些Key/Value类似的成对的基本数据类型,注意,它只能存储基本数据类型,也即int, long, boolean, String, float。事实上它完全相当于一个HashMap,唯一不同的就是HashMap中的Value可以是任何对象,而SharedPreferences中的值只能存储基本数据类型(primitive types)。

对于它的使用方法,可以参考Android Developer Guide,这里不重复。

如此来看,最适合SharedPreferences的地方就是保存配置信息,因为很多配置信息都是Key/Value。事实上,在Android当中SharedPreferences使用最多的地方也是用来保存配置(Settings)信息,系统中的Settings中这样,各个应用中的Settings也是这样。并且,Android中为了方便的使用SharedPreferences保存配置信息,它来专门有PreferenceActivity用来封装。也就是说如果你想在应用程序中创建配置(Settings),你可以直接使用PreferenceActivity和一些相关的专门为Preference封装的组件,而不用再直接去创建,读取和保存SharedPreference,Framework中的这些组件会为你做这些事。

再谈谈一些使用SharedPreference时的技巧,它只能保存基本数据类型,但假如我想保存一个数组,怎么办?可以把数据进行处理,把它转化成一个String,取出的时候再还原就好了;再如,如想保存一个对象,怎么办,同样,可以把对象序列化成为字符序列,或转成String(Object.toString()),或是把它的HashCode(Object.hashCode())当成Value保存进去。

总之,SharedPreferences使用起来十分的方便,可以灵活应用,因为它简单方便,所以能用它就尽量不要用文件或是数据库。

  1. Internal Storage内部存储空间

所谓的内部存储与外部存储,是指是否是手机内置。手机内置的存储空间,称为内部存储,它是手机一旦出厂就无法改变,它也是手机的硬件指标之一,通常来讲手机内置存储空间越大意味着手机价格会越贵(很多地方把它称为手机内存,但我们做软件的知道,这并不准确,内存是指手机运行时存储程序,数据和指令的地方;这里应该是手机内部存储的简称为内存,而并非严格意义上的内存)。

内部存储空间十分有限,因而显得可贵,所以我们要尽可能避免使用;另外,它也是系统本身和系统应用程序主要的数据存储所在地,一旦内部存储空间耗尽,手机也就无法使用了。所以对于内部存储空间,我们要尽量避免使用。上面所谈到的Shared Preferences和下面要谈到的SQLite数据库也都是存储在内部存储空间上的。

Android本身来讲是一个Linux操作系统,所以它的内部存储空间,对于应用程序和用户来讲就是“/data/data"目录。它与其他的(外部的存储)相比有着比较稳定,存储方便,操作简单,更加安全(因为可以控制访问权限)等优点。而它唯一的缺点就是它比较有限,比较可贵。

虽然,可以非常容易的知道程序本身的数据所在路径,所有的应用程序的数据路径都是“/data/data/app-package-name/”,所有的程序用到的数据,比如libs库,SharedPreferences都是存放在这个路径下面。但我们在使用的时候最好不要,或是千万不要直接引用这个路径。

使用内部存储主要有二个方式,一个是文件操作,一个是文件夹操作。无论哪种方式,Context中都提供了相应的函数来支持,使用Context不但操作简单方便,最重要的是Context会帮助我们管理这些文件,也可以方便帮助我们控制文件的访问权限。先来系统的说下Context中关于文件和文件夹操作的函数有哪些。

       a. 创建一个文件,并打开成一个文件输出流,需要提供一个String,作为文件名

  1. FileOutputStream  output = Context.openOutputFile(filename, Context.MODE_PRIVATE);  
  2. output.write(data);// use output to write whatever you like   
  3. output.close();  
 
  1. FileOutputStream  output = Context.openOutputFile(filename, Context.MODE_PRIVATE);     output.write(data);// use output to write whatever you like     output.close();  
       b.  同样,想打开一个文件作为输入的话,也是只需要提供文件名

 
  1. FileInputStream input = Context.openInputFile(filename);  
  2. input.read();  
  3. input.close();  
 
  1. FileInputStream input = Context.openInputFile(filename);     input.read();     input.close();  
       c.  列出所有的已创建的文件
 
  1. String[] files = Context.fileList();  
  2. for (String file : files) {  
  3.     Log.e(TAG, "file is " + file);  
  4. }  
 
  1. String[] files = Context.fileList();     for (String file : files) {         Log.e(TAG, "file is " + file);     }  
      d.  删除文件,能创建就要能够删除,当然也会提供了删除文件的接口,它也非常简单,只需要提供文件名

 
  1. if (Context.deleteFile(filename)) {  
  2.    Log.e(TAG, "delete file " + filename + " sucessfully“);  
  3. else {  
  4.    Log.e(TAG, "failed to delete file " + filename);  
  5. }  
 
  1. if (Context.deleteFile(filename)) {        Log.e(TAG, "delete file " + filename + " sucessfully“);     } else {        Log.e(TAG, "failed to delete file " + filename);     }  

      e.  获取文件已创建文件的路径,它返回一个文件对象用于操作路径

 
  1. File fileDir = Context.getFileDir();  
  2. Log.e(TAG, "fileDir " + fileDir.getAbsolutePath();  
 
  1. File fileDir = Context.getFileDir();     Log.e(TAG, "fileDir " + fileDir.getAbsolutePath();  
      f.  创建一个目录,需要传入目录名称,它返回 一个文件对象用到操作路径
 
  1. File workDir = Context.getDir(dirName, Context.MODE_PRIVATE);  
  2. Log.e(TAG, "workdir " + workDir.getAbsolutePath();  
 
  1. File workDir = Context.getDir(dirName, Context.MODE_PRIVATE);       Log.e(TAG, "workdir " + workDir.getAbsolutePath();  
       g. 以File对象方式查看所创建文件,需要传入文件名,会返回文件对象

 
  1. File store = Context.openFileStreamPath(filename);  
  2. Log.e(TAG, "store " + store.length());  
 
  1. File store = Context.openFileStreamPath(filename);       Log.e(TAG, "store " + store.length());  
      h. 获取Cache路径,无需要传入参数,返回文件对象

 
  1. File cachedir = Context.getCacheDir();  
  2. Log.e(TAG, "cachedir " + cacheDir.getAbsolutePath());  
 
  1. File cachedir = Context.getCacheDir();      Log.e(TAG, "cachedir " + cacheDir.getAbsolutePath());  
总结一下文件相关操作,可以得出以下三个特点:
      1. 文件操作只需要向函数提供文件名,所以程序自己只需要维护文件名即可;

      2. 不用自己去创建文件对象和输入、输出流,提供文件名就可以返回File对象或输入输出流

      3. 对于路径操作返回的都是文件对象。

相关推荐