Android存储对象到本地(SharedPreferences方式和file方式)

转自:http://blog.csdn.net/feng4656/article/details/8100372

我们知道SharedPreferences只能保存简单类型的数据,例如,String、int等。

如果想用SharedPreferences存取更复杂的数据类型(类、图像等),就需要对这些数据进行编码。

我们通常会将复杂类型的数据转换成Base64编码,然后将转换后的数据以字符串的形式保存在 XML文件中。

[java]  view plain copy
  1. public void saveOAuth(OAuthV1 oAuth_1) {  
  2.     SharedPreferences preferences = getSharedPreferences("base64",  
  3.             MODE_PRIVATE);  
  4.     // 创建字节输出流  
  5.     ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  6.     try {  
  7.         // 创建对象输出流,并封装字节流  
  8.         ObjectOutputStream oos = new ObjectOutputStream(baos);  
  9.         // 将对象写入字节流  
  10.         oos.writeObject(oAuth_1);  
  11.         // 将字节流编码成base64的字符窜  
  12.         String oAuth_Base64 = new String(Base64.encodeBase64(baos  
  13.                 .toByteArray()));  
  14.         Editor editor = preferences.edit();  
  15.         editor.putString("oAuth_1", oAuth_Base64);  
  16.   
  17.         editor.commit();  
  18.     } catch (IOException e) {  
  19.         // TODO Auto-generated  
  20.     }  
  21.     Log.i("ok""存储成功");  
  22. }  

之后将其解码:

[java]  view plain copy
  1. public OAuthV1 readOAuth() {  
  2.     OAuthV1 oAuth_1 = null;  
  3.     SharedPreferences preferences = getSharedPreferences("base64",  
  4.             MODE_PRIVATE);  
  5.     String productBase64 = preferences.getString("oAuth_1""");  
  6.               
  7.     //读取字节  
  8.     byte[] base64 = Base64.decodeBase64(productBase64.getBytes());  
  9.       
  10.     //封装到字节流  
  11.     ByteArrayInputStream bais = new ByteArrayInputStream(base64);  
  12.     try {  
  13.         //再次封装  
  14.         ObjectInputStream bis = new ObjectInputStream(bais);  
  15.         try {  
  16.             //读取对象  
  17.             oAuth_1 = (OAuthV1) bis.readObject();  
  18.         } catch (ClassNotFoundException e) {  
  19.             // TODO Auto-generated catch block  
  20.             e.printStackTrace();  
  21.         }  
  22.     } catch (StreamCorruptedException e) {  
  23.         // TODO Auto-generated catch block  
  24.         e.printStackTrace();  
  25.     } catch (IOException e) {  
  26.         // TODO Auto-generated catch block  
  27.         e.printStackTrace();  
  28.     }  
  29.     return oAuth_1;  
  30. }  

 需要导入一个包:commons-codec-1.4.jar

代码下载

本文为《Android/OPhone开发完全讲义》一书的内容连载。转载请注明出处

    我们知道SharedPreferences只能保存简单类型的数据,例如,String、int等。如果想用SharedPreferences存取更 复杂的数据类型(类、图像等),就需要对这些数据进行编码。我们通常会将复杂类型的数据转换成Base64编码,然后将转换后的数据以字符串的形式保存在 XML文件中。

Android SDK中并未提供Base64编码和解码库。因此,需要使用第三方的jar包。在本例中使用了Apache Commons组件集中的Codec组件进行Base64编码和解码。读者可以从如下的地址下载Codec组件的安装包。

http://commons.apache.org/codec/download_codec.cgi

    在Android工程目录的lib子目录中已经包含了Codec组件的jar包(commons-codec-1.4.jar),因此,读者可以在该工程中直接使用Codec组件。

    在本例中将一个Product类的对象实例和一个图像保存在XML文件中,并在程序重新运行后从XML文件装载Product对象和图像。下面是Product类的代码: 

package net.blogjava.mobile;
import java.io.Serializable;
//  需要序列化的类必须实现Serializable接口
public  class Product  implements Serializable
{
private String id;
private String name;
private  float price;
//  此处省略了属性的getter和setter方法
 

在存取数据之前,需要使用下面的代码创建一个SharedPreferences对象。

mySharedPreferences = getSharedPreferences("base64",Activity.MODE_PRIVATE);

其中mySharedPreferences是在类中定义的SharedPreferences类型变量。

在保存Product对象之前,需要创建Product对象,并将相应组件中的值赋给Product类的相应属性。将Product对象保存在XML文件中的代码如下:

Product product =  new Product();
product.setId(etProductID.getText().toString());
product.setName(etProductName.getText().toString());
product.setPrice(Float.parseFloat(etProductPrice.getText().toString()));
ByteArrayOutputStream baos =  new ByteArrayOutputStream();
ObjectOutputStream oos =  new ObjectOutputStream(baos);
//  将Product对象放到OutputStream中
oos.writeObject(product);
mySharedPreferences = getSharedPreferences("base64", Activity.MODE_PRIVATE);
//  将Product对象转换成byte数组,并将其进行base64编码
String productBase64 =  new String(Base64.encodeBase64(baos.toByteArray()));
SharedPreferences.Editor editor = mySharedPreferences.edit();
//  将编码后的字符串写到base64.xml文件中
editor.putString("product", productBase64);
editor.commit();

保存图像的方法与保存Product对象的方法类似。由于在保存之前,需要选择一个图像,并将该图像显示在ImageView组件中,因此,从ImageView组件中可以直接获得要保存的图像。将图象保存在XML文件中的代码如下:

ByteArrayOutputStream baos =  new ByteArrayOutputStream();
//  将ImageView组件中的图像压缩成JPEG格式,并将压缩结果保存在ByteArrayOutputStream对象中
((BitmapDrawable) imageView.getDrawable()).getBitmap().compress(CompressFormat.JPEG, 50, baos);
String imageBase64 =  new String(Base64.encodeBase64(baos.toByteArray()));
//  保存由图像字节流转换成的Base64格式字符串
editor.putString("productImage", imageBase64);
editor.commit();

    其中compress方法的第2个参数表示压缩质量,取值范围是0至100,0表示最高压缩比,但图像效果最差,100则恰恰相反。在本例中取了一个中间值50。

    从XML文件中装载Product对象和图像是保存的逆过程。也就是从XML文件中读取Base64格式的字符串,然后将其解码成字节数组,最后将字节数组转换成Product和Drawable对象。装载Product对象的代码如下:

String productBase64 = mySharedPreferences.getString("product", "");
//  对Base64格式的字符串进行解码
byte[] base64Bytes = Base64.decodeBase64(productBase64.getBytes());
ByteArrayInputStream bais =  new ByteArrayInputStream(base64Bytes);
ObjectInputStream ois =  new ObjectInputStream(bais);
//  从ObjectInputStream中读取Product对象
Product product = (Product) ois.readObject();

装载图像的代码如下:
String imageBase64 = mySharedPreferences.getString("productImage","");
base64Bytes = Base64.decodeBase64(imageBase64.getBytes());
bais =  new ByteArrayInputStream(base64Bytes);
//  在ImageView组件上显示图像
imageView.setImageDrawable(Drawable.createFromStream(bais,"product_image"));

在上面的代码中使用了Drawable类的createFromStream方法直接从流创建了Drawable对象,并使用setImageDrawable方法将图像显示在ImageView组件上。

在 这里需要提一下的是图像选择。在本例中使用了res\drawable目录中的除了icon.png外的其他图像。为了能列出这些图像,本例使用了 Java的反射技术来枚举这些图像的资源ID。基本原理是枚举R.drawable类中所有的Field,并获得这些Field的值。如果采用这个方法, 再向drawable目录中添加新的图像,或删除以前的图像,并不需要修改代码,程序就可以显示最新的图像列表。枚举图像资源ID的代码如下:
//  获得R.drawable类中所有的Field
Field[] fields = R.drawable. class.getDeclaredFields();
for (Field field : fields)
{
if (!"icon".equals(field.getName()))
imageResIdList.add(field.getInt(R.drawable. class));
}

    运行本例后,单击【选择产品图像】按钮,会显示一个图像选择对话框,如图1所示。选中一个图像后,关闭图像选择对话框,并单击【保存】按钮。如果保存成功,将显示如图2所示的提示对话框。当再次运行程序后,会显示上次成功保存的数据。

 

 
查看base64.xml文件,会看到如下的内容:

<? xml version='1.0' encoding='utf-8' standalone='yes'  ?>
< map >
< string  name ="productImage" >/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABDsyj7yK3 </ string >
< string  name ="product" >rO0ABXNyABtuZXQuYmxvZ2phdmEubW9iaWxlLlByb2 </ string >
</ map >

android File存储对象

1、保存对象到本地或SD卡

[java]  view plain copy
  1.               public void fileSave(OAuthV1 oAuth_1){  
  2.     //保存在本地  
  3.     try {  
  4.         // 通过openFileOutput方法得到一个输出流,方法参数为创建的文件名(不能有斜杠),操作模式  
  5.         FileOutputStream fos = this.openFileOutput("oauth_1.out",Context.MODE_WORLD_READABLE);  
  6.         ObjectOutputStream oos = new ObjectOutputStream(fos);  
  7.         oos.writeObject(oAuth_1);// 写入  
  8.         fos.close(); // 关闭输出流  
  9.         //Toast.makeText(WebviewTencentActivity.this, "保存oAuth_1成功",Toast.LENGTH_LONG).show();  
  10.     } catch (FileNotFoundException e) {  
  11.         e.printStackTrace();  
  12.         //Toast.makeText(WebviewTencentActivity.this, "出现异常1",Toast.LENGTH_LONG).show();  
  13.     } catch (IOException e) {  
  14.         e.printStackTrace();  
  15.         //Toast.makeText(WebviewTencentActivity.this, "出现异常2",Toast.LENGTH_LONG).show();  
  16.     }  
  17.       
  18.     //保存在sd卡  
  19.     if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){  
  20.           
  21.            File sdCardDir = Environment.getExternalStorageDirectory();//获取SDCard目录  
  22.            File sdFile = new File(sdCardDir, "oauth_1.out");  
  23.              
  24.       
  25.         try {  
  26.             FileOutputStream fos = new FileOutputStream(sdFile);  
  27.             ObjectOutputStream oos = new ObjectOutputStream(fos);  
  28.             oos.writeObject(oAuth_1);// 写入  
  29.             fos.close(); // 关闭输出流  
  30.         } catch (FileNotFoundException e) {  
  31.             // TODO Auto-generated catch block  
  32.             e.printStackTrace();  
  33.         } catch (IOException e) {  
  34.             // TODO Auto-generated catch block  
  35.             e.printStackTrace();  
  36.         }  
  37.            //Toast.makeText(WebviewTencentActivity.this, "成功保存到sd卡", Toast.LENGTH_LONG).show();  
  38.              
  39.     }  
  40. }  
需要注意的是,要保存的对象(OAuthV1)一定要实现了Serializable接口。

实现了Serializable接口对象才能被序列化。


2、从本地或SD卡中取出对象

(从本地取得保存的对象)

[java]  view plain copy
  1.               public OAuthV1 readOAuth1() {  
  2. OAuthV1 oAuth_1 = null;  
  3. //String filename = "oauth_file.cfg";  
  4.         try {  
  5.             FileInputStream fis=this.openFileInput("oauth_1.out");   //获得输入流  
  6.             ObjectInputStream ois = new ObjectInputStream(fis);  
  7.             oAuth_1 = (OAuthV1)ois.readObject();  
  8.               
  9.             //tv.setText(per.toString());                           //设置文本控件显示内容  
  10.            // Toast.makeText(ShareTencentActivity.this,"读取成功",Toast.LENGTH_LONG).show();//弹出Toast消息  
  11.         } catch (StreamCorruptedException e) {  
  12.             //Toast.makeText(ShareTencentActivity.this,"出现异常3",Toast.LENGTH_LONG).show();//弹出Toast消息  
  13.             e.printStackTrace();  
  14.         } catch (OptionalDataException e) {  
  15.             //Toast.makeText(ShareTencentActivity.this,"出现异常4",Toast.LENGTH_LONG).show();//弹出Toast消息  
  16.             e.printStackTrace();  
  17.         } catch (FileNotFoundException e) {  
  18.             //Toast.makeText(ShareTencentActivity.this,"出现异常5",Toast.LENGTH_LONG).show();//弹出Toast消息  
  19.             e.printStackTrace();  
  20.         } catch (IOException e) {  
  21.             e.printStackTrace();  
  22.         } catch (ClassNotFoundException e) {  
  23.             //Toast.makeText(ShareTencentActivity.this,"出现异常6",Toast.LENGTH_LONG).show();//弹出Toast消息  
  24.             e.printStackTrace();  
  25.         }  
  26. return oAuth_1;  

(2)从SD卡中取得保存的对象

[java]  view plain copy
  1. public OAuthV1 readOAuth2() {  
  2.     OAuthV1 oAuth_1 = null;  
  3.     File sdCardDir = Environment.getExternalStorageDirectory();//获取SDCard目录  
  4.     File sdFile = new File(sdCardDir, "oauth_1.out");  
  5.       
  6.     try {  
  7.         FileInputStream fis=new FileInputStream(sdFile);   //获得输入流  
  8.         ObjectInputStream ois = new ObjectInputStream(fis);  
  9.         oAuth_1 = (OAuthV1)ois.readObject();  
  10.         ois.close();  
  11.     } catch (StreamCorruptedException e) {  
  12.         // TODO Auto-generated catch block  
  13.         e.printStackTrace();  
  14.     } catch (OptionalDataException e) {  
  15.         // TODO Auto-generated catch block  
  16.         e.printStackTrace();  
  17.     } catch (FileNotFoundException e) {  
  18.         // TODO Auto-generated catch block  
  19.         e.printStackTrace();  
  20.     } catch (IOException e) {  
  21.         // TODO Auto-generated catch block  
  22.         e.printStackTrace();  
  23.     } catch (ClassNotFoundException e) {  
  24.         // TODO Auto-generated catch block  
  25.         e.printStackTrace();  
  26.     }  
  27.           }  
对SD卡操作别忘了加权限

[html]  view plain copy
  1.         <!-- 在SDCard中创建与删除文件的权限 -->  
  2. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>  
  3. <!-- 往SDCard写入数据的权限 -->  
  4. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值