以下是小编精心整理的android 数据存储之SharedPreferences(共含10篇),仅供参考,希望能够帮助到大家。同时,但愿您也能像本文投稿人“阿蒙”一样,积极向本站投稿分享好文章。
简述:Shared Preferences常用于一些属性设置,参数设置,用来保存一些简单的数据,例如本例中,用来保存应用的播放状态。重点:无法直接在多个应用程序间共享Preferences数据。
简单的使用方法:1、调用getPreferences方法得到一个SharedPreferences对象。参数可直接写0,意思为私有。
2、调用SharedPreferences的edit()方法得到一个Editor对象,
3、通过Editor.put...()方法输入数据
4、最后通过Editor的commit方法提交数据。
当我们再次进入程序的时候可以通过SharedPreferences的get....();方法取得保存的数据。然后根据数据做相应的操作。
那么,数据到底放在什么地方了呢?
打开DDMS视图,数据保存在了/data/data目录下,相应的应用程序目录下会生成一个shared_prefs文件夹,里面就是我们存储数据的一个xml文件。比如本例如图:
Shareepreference 是android提供的一个轻量级的数据存储框架,形式就是键值对的形式,熟悉xml的朋友应该比较习惯这种风格,就是“属性名-属性值”的形式,从名字就可以看出,这个框架主要是用于设置用户的一个偏好,他的一个特点是可以跨session的共享,在多个activity之间可以操作,如果设置特别的权限,其他应用也可以访问。下面就是使用的一个基本方法。
1:获取类型SharedPreferences
主要有两种方式可以获得
getSharedPreferences (String name, int mode)接受两个参数,第一个是文件标示,第二个是权限,用于创建多个配置文件的场景
//name为文件名,注:不加后缀。如果不存在的话,会自动创建。保存的数据是存放在data/data/ 你的包名/name.xml文件中
getPreferences( int mode)- 只有文件权限参数,与上一个不同在于只创建一个文件。
//mode操作模式,共4种,如下:
MODE_PRIVATE 这是默认的形式,配置文件只允许本程序和享有本程序ID的程序的访问
MODE_WORLD_READABLE 允许其他的应用程序读文件
MODE_WORLD_WRITEABLE 允许其他的应用程序写文件
MODE_MULTI_PROCESS 主要用于多任务,2.3版本当多个进程共同访问的时候,必须指定这个标签
Editor来进行偏好的编辑与设置,
Editor主要包含一些putXXX方法,支持booleans, floats, ints, longs, and strings.几种类型,最后完成添加后,一定要调用commit方法或者apply方法进行修改后的提交。
如果想得到value的话就自己直接用SharedPreference类来使用相应的getxxx方法就好了。
SharedPreferences myPreference = this.getSharedPreferences(“filename”, Context.MODE_PRIVATE);
Editor editor = myPreference.edit();
editor.putString(“COLOR”, “red”);
editor.commit();
clear()用来删除所有的 数据
remove(String key)用来根据保存的键值进行删除
这两个函数都返回的是是SharedPreferences.Editor 在返回以后,需要commit()
做开发肯定离不了数据,因为编程=算法+数据,做Android应用开发常用到的数据存储方式有以下五种:
1 ,使用SharedPreferences存储数据 2, 文件存储数据 3 ,SQLite数据库存储数据 4 ,使用ContentProvider存储数据 5, 网络存储数据 今天就简单介绍下第一种存储方式:使用SharedPreferences存储数据。 ---------------------------使用SharedPreferences存储数据-----------------------------------------------------SharePreference 是一个轻量级的存储机制。只能存储一些基础类型,以xml文件为载体。文件存放路径为data/data/包名/share_prefs/文件名.xml存储的时候类似于Map,key-Value值对。存放数据的时候需要调用到SharePreference接口的一个editor属性,通过editor进行数据添加,移除等操作数据,而且必须调用editor的commit方法。
xmlns:tools=“schemas.android.com/tools”
android:id=“@+id/LinearLayout1”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:orientation=“vertical” >
android:id=“@+id/input_edt”
android:layout_width=“fill_parent”
android:layout_height=“wrap_content”
android:hint=“请输入保存内容” />
android:id=“@+id/save_btn”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:text=“保存数据” />
----------------存取数据操作----------------------------------
public class MainActivity extends Activity implements OnClickListener {
/**内容输入框 */
private EditText inputEdt;
/**保存按钮 */
private Button saveBtn;
/**SharedPreferences*/
private SharedPreferences mSharedPreferences;
/**Editor*/
private Editor mEditor;
private static final String SAVE_FILE_NAME = “save_spref”;
private static final String SAVE_FILE_KEY = “save_key”;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewsById;
mSharedPreferences = getSharedPreferences(SAVE_FILE_NAME, MODE_PRIVATE);
mEditor = mSharedPreferences.edit();
/**如果要取得对应的值*/
String getContent = mSharedPreferences.getString(SAVE_FILE_KEY, “”);
inputEdt.setText(getContent);
}
private void findViewsById() {
inputEdt = (EditText) findViewById(R.id.input_edt);
saveBtn = (Button) findViewById(R.id.save_btn);
saveBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.save_btn) {
String content = inputEdt.getText().toString();
mEditor.putString(SAVE_FILE_KEY, content);
}
}
/**
* mSharedPreferences=getSharedPreferences(SAVE_FILE_NAME, MODE_PRIVATE);//
方法的第一个参数用于指定该文件的名称,名称不用带后缀,后缀会由Android自动加上;
方法的第二个参数指定文件的操作模式,共有四种操作模式,
四种操作模式分别为:
1. MODE_APPEND: 追加方式存储
2. MODE_PRIVATE: 私有方式存储,其他应用无法访问
3. MODE_WORLD_READABLE: 表示当前文件可以被其他应用读取
4. MODE_WORLD_WRITEABLE: 表示当前文件可以被其他应用写入
*/
}
android应用大多数用的java开发,所以java的文件操作在android中完全适用,只不过android对手机而言,多了个外存储设置SD卡,
----------------------------------------------简单的界面布局-----------------------------------------------------------
xmlns:tools=“schemas.android.com/tools”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:orientation=“vertical” >
android:id=“@+id/input_edt”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:hint=“请输入保存内容” />
android:id=“@+id/write_btn”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:text=“保存数据” />
android:id=“@+id/read_btn”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:text=“读取数据” />
-----------------------------功能代码-----------------------------------------------------------
public class MainActivity extends Activity implements OnClickListener {
/**内容输入框 */
private EditText inputEdt;
/**保存(写入)按钮 */
private Button writeBtn;
/**读取按钮 */
private Button readBtn;
/**要保存的文件名*/
private static final String FILE_NAME = “temp_file.txt”;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewsById();
}
private void findViewsById() {
inputEdt = (EditText) findViewById(R.id.input_edt);
writeBtn = (Button) findViewById(R.id.write_btn);
readBtn = (Button) findViewById(R.id.read_btn);
writeBtn.setOnClickListener(this);
readBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.write_btn:
writeData();
break;
case R.id.read_btn:
String result = readData();
inputEdt.setText(result);
break;
}
}
/*
* 方法openFileOutput(FILE_NAME, Activity.MODE_PRIVATE); 参数说明:以FILE_NAME文件名,Activity.MODE_PRIVATE文件的应用模式,打开一个输出流如果文件不存系统会为你创建一个 注意这里的文件名称不能包括任何的/或者/这种分隔符,只能是文件名
* 该文件会被保存在/data/data/应用名称/files/temp_file.txt 文件的操作模式有以下四种:MODE_PRIVATE 私有(只能创建它的应用访问) 重复写入时会文件覆盖MODE_APPEND 私有 重复写入时会在文件的末尾进行追加,而不是覆盖掉原来的文件 MODE_WORLD_READABLE 公用 可读 MODE_WORLD_WRITEABLE 公用 可读写
*/
private void writeData() {
String content = inputEdt.getText().toString();
try {
FileOutputStream utputStream = openFileOutput(FILE_NAME, Activity.MODE_PRIVATE);
outputStream.write(content.getBytes());
outputStream.flush();
outputStream.close();
Toast.makeText(MainActivity.this, “保存成功”, Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 把刚刚保存的数据读出来
* */
private String readData() {
String content = “”;
try {
FileInputStream inputStream = this.openFileInput(FILE_NAME);
byte[] bytes = new byte[1024];
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
while (inputStream.read(bytes) != -1) {
arrayOutputStream.write(bytes, 0, bytes.length);
}
inputStream.close();
arrayOutputStream.close();
content = new String(arrayOutputStream.toByteArray());
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
/****************上面的内容是把内容存到手机内存中*************************************/
/**判断SDcard是否存在并且可读写*/
private boolean isSDcardExist() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
return true;
} else {
Toast.makeText(getApplicationContext(), “内存卡不可用”, 1000).show();
return false;
}
}
/**往内存卡中存文件*/
public void writeToSDCard(String filename, String filecontent) throws Exception {
File file = new File(Environment.getExternalStorageDirectory(), filename);
FileOutputStream utStream = new FileOutputStream(file);
outStream.write(filecontent.getBytes());
outStream.close();
}
/**读SD卡中对应文件的内容*/
private String readSDCardFile(String filePath, String fileName) {
String result = “”;
try {
File file = new File(filePath, fileName);
FileInputStream is = new FileInputStream(file);
byte[] b = new byte[is.available()];
is.read(b);
result = new String(b);
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
}
---------注:-------------------------------------------
SD卡操作不要忘记在AndroidManifest.xml中添加对应权限:
Android系统一共提供了四种数据存储方式,分别是:SharePreference、SQLite、Content Provider和File。由于Android系统中,数据基本都是私有的的,都是存放于“data/data/程序包名”目录下,所以要实现数据共享,正确方式是使用Content Provider。
SQLite: SQLite是一个轻量级的数据库,支持基本SQL语法,是常被采用的一种数据存储方式。Android为此数据库提供了一个名为SQLiteDatabase的类,封装了一些操作数据库的API。
SharedPreference: 除SQLite数据库外,另一种常用的数据存储方式,其本质就是一个xml文件,常用于存储较简单的参数设置。
File: 即常说的文件(I/O)存储方法,常用语存储大数量的数据,但是缺点是更新数据将是一件困难的事情。
ContentProvider: Android系统中能实现所有应用程序共享的一种数据存储方式,由于数据通常在各应用间的是互相私密的,所以此存储方式较少使用,但是其又是必不可少的一种存储方式。例如音频,视频,图片和通讯录,一般都可以采用此种方式进行存储。每个Content Provider都会对外提供一个公共的URI(包装成Uri对象),如果应用程序有数据需要共享时,就需要使用Content Provider为这些数据定义一个URI,然后其他的应用程序就通过Content Provider传入这个URI来对数据进行操作,
PS: URI由3个部分组成:“content://”、数据的路径、标识ID(可选)。
SQLite是一种转为嵌入式设备设计的轻型数据库,其只有五种数据类型,分别是:
NULL: 空值
INTEGER: 整数
REAL: 浮点数
TEXT: 字符串
BLOB: 大数据
在SQLite中,并没有专门设计BOOLEAN和DATE类型,因为BOOLEAN型可以用INTEGER的0和1代替true和false,而DATE类型则可以拥有特定格式的TEXT、REAL和INTEGER的值来代替显示,为了能方便的操作DATE类型,SQLite提供了一组函数,详见:www.sqlite.org/lang_datefunc.html。这样简单的数据类型设计更加符合嵌入式设备的要求。关于SQLite的更多资料,请参看:www.sqlite.org/
在Android系统中提供了android.database.sqlite包,用于进行SQLite数据库的增、删、改、查工作。其主要方法如下:
beginTransaction: 开始一个事务。
close(): 关闭连接,释放资源。
delete(String table, String whereClause, String[] whereArgs): 根据给定条件,删除符合条件的记录。
Android提供了多种方式(XML文件方式、文件方式、数据库方式等)进行数据的存储,开发者可以根据数据类型和设计的需要,选择适当的存储方式进行数据存储。
1.XML文件管理
XML文件更多的是用来维护应用或系统的配置文件。在Android中,goole提供了SharedPreferences这个轻型的存储类作为XML文件存储的上层接口,其本质上就是
根据配置信息是否对其他应用开放,SharedPreferences提供了MODE_PRIVATE.、MODE_WORLD_READABLE两种权限。SharedPreferences的操作分为获取配置信息和存储配置信息两种方式。下面是获取配置信息的方法:
SharedPreferences settings=getSharedPreferences(PREFS_NAME,MODE_PRIVATE);
boolean silent=settings.getBoolean(“silentMode”, false);
存储配置信息和获取配置信息略有不同,下面是存储配置信息的方法:
SharedPreference settings=getShatedPreferences(PREFS_NAME, MODE_PRIVATE);
SharedPreference.Editor editor=settings.edit(); //获得编辑器
editor.putBoolean(“silentMode”, mSilentMode);
editor.commit(); //提交
如果希望配置信息对其他应用开发,在设置权限时,可使用MODE_WORLD_READABLE。在其他应用希望获取相应的配置信息时,必须先获取相应的上下文,方法如下:
context=createPackageContext(“com.miaozl.text”, Context.CONTEXT_IGNORE_SECURITY);
if(context != null){
SharedPreference settings=context.getSharedPreference(PREFS_NAME,Context.MODE_WORLD_READABLE);
mTest=settings.getString(“text”, null);
}
需要说明的是,在PreferenceActivity中内置了对SharedPreferences的支持。
如果希望ListPreference保存或查看当前的选择,可以调用的ListPreferences方法如下:
public void setValue(String value) //对应“android:entries”属性的值
public void setValueIndex(int index) //对应“android:entryValues”属性的值
public String getValue()
其他的Preference的操作方法类似于ListPreference。
2.内部文件管理
对于二进制数据,Android提供了内部存储的方式,开发者可以将数据存储在应用的私有空间中,避免其他程序的访问,内部存储的数据会在应用卸载时删除。
内部存储的实现非常简单,其权限包括MODE_PRIVATE、MODE_APPEND、MODE_WORLD_READABLE、MODE_WORLD_WRITEABLE等。
内部存储所在目录为datadatacom.company.packagenamefiles。如果文件名为wors,其内部存储的目录为datadatacom.android.mmsfileswords。
(1)写入数据
写入字符串数据的方法:
FileOutputStream ut=context.openFileOutput(file,Context.MODE_WORLD_WRITEABLE);
out.write(captureArray.toString().getBytes());
out.close();
写入结构体数据的方法:
private static void writeConfiguration(Context context, LocaleConfiguration configuration){
DataOutputStream ut = null;
ut=new DataOutputStream(context.openFileOutput(PREFERENCES, MODE_PRIVATE));
out.writeUTF(configuration.locale);
out.writeInt(configuration.mcc);
out.writeInt(configuration.mnc);
out.flush();
}
(2)读取数据
读取字符串数据的方法:
StringBuilder sb=new StringBuilder();
FileInputStream words=context.openFileInput(“word”);
int c;
while((c=words.read()) != -1){
if(c=='r' || c=='n'){
String word=sb.toString().trim();
if(word.length() > 0){
mWord.add(word);
}
sb.setLength(0);
}else{
sb.append((char)c);
}
}
words.close();
mWordCount=mWords.size();
读取数据结构数据的方法:
private static void readConfiguration(Context context, LocaleConfiguration configuration){
DataInputStream in=null;
in=new DataInputStream(context.openFileInput(PREFERENCES));
configuration.locale=in,readUTF();
configuration.mcc=in.readInt();
configuration.mnc=in.readInt();
in.close();
对于应用携带的静态数据,可以放置在应用的assets目录或res、raw目录下,
对于assets目录下的静态数据,存在单个文件最大仅支持1MB的局限,读取方式:InputStream is=getAssets().open(“read_asset.txt”);
对于res、raw目录下的静态数据,读取方式:InputStream.inputStream=resources.openRawResource(R.raw.definitions);
Android还对创建缓存提供了支持,通过getCacheDir()可以获取应用的缓存路径。在系统可用空间不足时,Android会清空缓存,但对于开发者而言,不应维护过多的缓存。和内部存储一样,在应用卸载时,会清空并删除缓存目录。
3.外部文件管理
为了便于进行媒体文件的扫描,Android为媒体文件设置了特定目录,目前Android支持DIRECTORY_MUSIC、DIRECTORY_PODCASTS、DIRECTORY_RINGTONES、DIRECTORY_ALARMS、DIRECTORY_NOTIFICATIONS、DIRECTORY_PICTURES、DORECTORY_MOVIES、DIRECTORY_DOWNLOADS等目录。
Android开始支持在SD卡上的应用私有目录,通过getExtenalFilesDir()可以获取具体路径。该具体路径依赖应用的包名,如com.miaozl.helle,其SD卡上的应用私有目录为mntsdcardAndroiddatacom.miaozl.hellofiles。下面是获取图片路径的方法:File path=getExternalFilesDir(Environment.DIRECTORY_PICTURES)。
如果希望存储在SD上的公共目录下,则可通过getExternalStoragePublicDirectory可以获得公共目录,但需要注意,公共目录的具体路径视需要存储的文件的类型而定。下面是获取公共目录的方法:
String sdroot=Environment.getExternalStorageDirectory().getAbsolutePath();
String dwndir=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
SD上的应用私有目录和内部存储一样,在应用卸载时,将会被清空并删除。
如果应用需要的缓存较大,也可以在SD卡上建立缓存目录,通过getExternalCacheDir()可以获取应用在SD卡上的缓存路径。
在使用SD卡目录时,需要注意SD卡是否挂载,可通过Environment.getExternalStorageState()方法进行判断。如果返回值为Environment.MEDIA_MOUNTED,表示SD卡处于挂载状态,可以放心使用。
4.数据库管理
通过数据库的方式可以存储复杂的数据,也可以方便对数据的操作,因此数据库存储在Android中非常有用。目前,Android采用SQLite3数据库。SQLite3数据库是一种适合嵌入式平台的轻量级数据库。但是开源版本的SQLite3没有对数据进行加密保护,因此存储敏感数据是一个十分头疼的问题。好在SQLite3在框架层提供了加密算法的接口,有需要的开发者可以自行添加相关的加密算法。
Android提供了两种SQLite的实现方法,一种是基于Android封装接口来实现的,适合对数据库要求不高或对SQLite不熟悉的开发者;另一种是基于原生SQLite的方法来实现的,可以完全发挥出SQLite的能力,性能稍好,但对SQLite的理解要求较高。至于采用何种实现方法,开发者可以根据应用场和自己对SQLite的理解程度自行把握。
对于数据读取频繁的场景,必须考虑SQLite的性能,在Android平台上,使用原始SQL语句的执行效率要比封装过的ContentProvider高;对于一次性进行多项处理的场景,应考虑通过事务处理的方式进行批量处理。
(1)Android封装接口
考虑到数据库的操作很频繁,在Android中提供了封装类,即SQLiteOpenHelper,通过集成SQLiteOpenHelper,开发者可以很容易地设计和操作数据库。需要注意的是,封装会使Android的性能降低。
在继承SQLiteOpenHelper时,必须实现onCreate和onUpgrade方法。下面是通过Android封装接口设计数据库的一般步骤:定义数据库名、数据库版本号、数据表名。实现onCreate和onUpgrade方法。实现插入、更新、删除和查询方法。
实现onCreate方法:
public void onCreate(SQLiteDatabase db){
db.execSQL(“CREATE TABLE ”+NOTES_TABLE_NAME+“(” + NoteColumns._ID+ “ INTEGER PRIMARY KEY,”+NoteColumns.TITLE+“ TEXT,”
+NoteColumns.NOTE+“ TEXT,”+NoteColumns.CREATED_DATE+“ INTEGER,” +NoteColumns.MODIFIED_DATE+“ INTEGER”+“);”);
}
实现onUpgrade方法:
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
db.execSQL(“DROP TABLE IF EXISTS notes”);
onCreate(db);
}
事务处理的相关方法:
public void begintransaction()
public void beginTransactionWithListener(SQLiteTransactionListener transactionListener)
public void endTransaction()
public boolean inTreansaction()
public void setTransactionSuccessful()
(2)原生方法处理
因为最近有人问我怎么保存HttpClient的Cookie, 所以这里写下, 顺便记录总结吧. 当然, 有Android网络编程经历的童鞋一看就懂喇~
就不多说了, 直接上代码:
/** * 本地存储Cookie * @param response */ private void saveCookies(HttpResponse response) { SharedPreferences preferences = getSharedPreferences(cookies, MODE_PRIVATE); List
String“ httpentity=”HttpEntity“ httpget=”HttpGet“ httpgeturl=”HttpGet(url);“ httpresponse=”HttpResponse“ ifresponse.getstatusline.getstatuscode=”if(response.getStatusLine().getStatusCode()“ log.etag=”Log.e(TAG,“ mode_private=”MODE_PRIVATE);“ pre=”pre“ response=”client.execute(get);“ sharedpreferences=”SharedPreferences“ sharedpreferences.getstringcookies=”sharedPreferences.getString(cookies,“ try=”try“ url=”www.host.com/test;“ 保存失败=”保存失败);“ 保存成功=”保存成功);“>
这样即使退出应用后, 下次重新使用Cookie, 也可以避免一些重复的HTTp请求, 比如重复登录什么的. 但是要注意一个地方, Cookie是有效期的, 如果超过有效期再去使用就会无效, 需要重新登录才能进行其他的操作. 如上面的代码, 测试的Cookie有效时间是一个月.
所以在使用Cookie, 可以同时保存Cookie的有效期, 当然不保存也可以, 携带无效Cookie去访问是服务器自然也会返回相应的提示, 根据提示响应即可. 另外唠嗑唠嗑, Cookie是一种很简单的文本数据, 记录了服务器和客户端之间的访问信息, 因此读取和存储, 管理的效率很高, 但不好的是不够安全, 本地化存储最好注意安全. 当然如果不是什么很重要的数据, 并且有良好的使用习惯, 也没什么.
上面是针对Android开发环境中原生的HttpClient, 如果是使用其他Apache的HttpClient jar包, 比如commons-httpclient-3.1.jar. 可能会发现上面的方法使用起来并不方便, 那么我们还可以模仿浏览器处理Cookie的策略, 使用该jar包中特有的httpPost.setRequestHeader()方法添加访问信息, 比如
httpPost.setRequestHeader(Host, host地址);
httpPost.setRequestHeader(Connection,Keep-Alive);
httpPost.setRequestHeader(Cookie, cookie);
httpPost.setRequestHeader(User-Agent, userAgent);
然后, 我们利用抓包工具, 随便查看电脑浏览器的某个请求, 能看到Headers中有类似格式的Cookie数据(下图是访问有道网站的请求):
可见, 这种处理方式跟浏览器的策略是类似的.
软件中永远绕不开的一个问题就是数据存储的问题,PC的时候一般都是选择在数据库中存储,iOS如果是和后端配合的话,那么不需要考虑数据存储的这个问题,上次写了一下plist的存储,不过数据都是存储一些简单的键值对对象,本次需要将一些自己定义的类型存储在plist比如说图片,这个时候可以利用NSCoding协议,将数据地以类似档案的形式存储到plist文件中,然后从plist的文件中读取数据,使用协议的时候这个时候就会用到了NSCoder,如果对存档和解压没有概念的话,可以简单的理解为数据的序列化与反序列化。
基础概念
NSCoding是一个protocol. 如果实现了NSCoding,需要实现其中的两个方法:
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (id)initWithCoder:(NSCoder *)aDecoder; // NS_DESIGNATED_INITIALIZER
方法中的主要的参数就是NSCoder,它是archivie字节流的抽象类.可以将数据写入一个coder,也可以从coder中读取我们写入的数据. NSCoder是一个抽象类,不能直接使用它来创建对象. 但是可以通过其子类NSKeyedUnarchiver从字节流中读取数据,NSKeyedArchiver将对象写入到字节流。本文以书籍为例:
新建一个Book类,Book.h中的代码:
#import
#import
@interface Book : NSObject
@property (strong,nonatomic) UIImage *ConverPicture;
@property (strong,nonatomic) NSString *BookName;
@property (strong,nonatomic) NSString *Author;
@property (strong,nonatomic) NSNumber *Price;
@end
Book.m中实现NSCoding的两个方法,注意中UIImage的写法与其他有所不同:
@implementation Book
- (void)encodeWithCoder:(NSCoder *)aCoder{
//注意这里是存储的是JPG图片的调用
[aCoder encodeObject:UIImageJPEGRepresentation(self.ConverPicture,1.0)forKey:@”ConverPicture“];
[aCoder encodeObject:_BookName forKey:@”BookName“];
[aCoder encodeObject:_Author forKey:@”Author“];
[aCoder encodeObject:_Price forKey:@”Price“];
}
- (id)initWithCoder:(NSCoder *)aDecoder{
self.ConverPicture=[UIImage imageWithData:[aDecoder decodeObjectForKey:@”ConverPicture“]];
self.BookName=[aDecoder decodeObjectForKey:@”BookName“];
self.Author=[aDecoder decodeObjectForKey:@”Author“];
self.Price=[aDecoder decodeObjectForKey:@”Price“];
return self;
}
@end
Demo实现
正常的情况的不需要新建页面的,不过需要演示一下UIImage的效果,Main.storyboard中的布局:
稍微解释一下,前两个是存的单文件,后两个存的是多文件,UIImage展示存储的图片:
ViewController定义字段:
@property (strong,nonatomic) NSString *storagePath;
@property (strong,nonatomic) NSString *storageListPath;
@property (strong,nonatomic) NSMutableArray *bookList;
设置路径,如果不是很清晰,可参考本文之前的博客:
NSArray *codepath= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
_storagePath = [codepath[0] stringByAppendingPathComponent:@”book.plist“];
NSLog(@”%@“,NSHomeDirectory());
_storageListPath = [codepath[0] stringByAppendingPathComponent:@”booklist.plist“];
单个存档:
Book *book=[[Book alloc]init];
UIImage *image=[UIImage imageNamed:@”Code1.jpg“];
book.ConverPicture=image;
book.BookName=@”百年孤独“;
book.Author=@”加西亚.马尔克斯“;
book.Price=[[NSNumber alloc] initWithInteger:45];
if ([NSKeyedArchiver archiveRootObject:book toFile:_storagePath]) {
NSLog(@”数据存档成功“);
}
单个解压:
Book *decodeBook=[NSKeyedUnarchiver unarchiveObjectWithFile:_storagePath];
self.myImageView.image=decodeBook.ConverPicture;
NSLog(@”%@“,decodeBook.ConverPicture);
NSLog(@”%@“,decodeBook.BookName);
NSLog(@”解档成功“);
多个存档:
self.bookList=[NSMutableArray array];
for (NSInteger i=1; i<3; i++) {
Book *book=[[Book alloc]init];
NSString *imageName=[NSString stringWithFormat:@”Code%ld.jpg“,(long)i];
UIImage *image=[UIImage imageNamed:imageName];
book.ConverPicture=image;
book.BookName=[NSString stringWithFormat:@”百年孤独%ld“,(long)i];
book.Author=[NSString stringWithFormat:@”加西亚.马尔克斯%ld“,(long)i];
book.Price=[[NSNumber alloc] initWithInteger:45];
[self.bookList addObject:book];
}
if ([NSKeyedArchiver archiveRootObject:self.bookList toFile:_storageListPath]) {
NSLog(@”数据存档成功“);
}
多个解档:
self.bookList=[NSKeyedUnarchiver unarchiveObjectWithFile:_storageListPath];
Book *nextBook=self.bookList[1];
self.myImageView.image=nextBook.ConverPicture;
NSLog(@”解档成功");
通过代码基本上发现其实存档和解压是非常简单的一个事情,不过事实这种方式缺点还是很明显的,以这种方式保存数据只能一次性归档保存以及一次性解压,
数据较少的时候如果使用感觉比较方便,数据量过多的时候如果想修改其中的某一条,解压整个数据然后归档整个数据还是比较耗时的
Twitter已经从以往的数据存储开发经验中提出一个名为 Gizzard的Scala框架,让用户可以更方便地创建自定义容错、分布式数据库,Twitter给出了一个名为“Rowz”的示例,方便用户上手,
Twitter还公布了Gizzard的完整代码。有了Gizzard,初创公司和小公司就可以更好更快地处理大量数据,从而利用更少的资源满足用户需 求。
项目主页:www.open-open.com/lib/view/home/1339141537578
MckoiDDB 是一个支持低延迟的随机存取(读,写)的数据库,涵盖了网络上的机器集群分布式数据库查询系统,该软件提供了管理数据在网络上集群和用于访问和查询数据的 客户端API存储系统,
该系统可通过在网络中添加或删除节点来自由扩展MckoiDDB的规模,使一个应用程序的逻辑数据模型的设计和执行灵活。 MckoiDDB可以安装在高速专用网络及云服务提供者的实例。
项目主页:www.open-open.com/lib/view/home/1322727454952