【
Android 中数据的本地存储
存储方式:
一、SharedPreferences 轻量级存储
二、文件存储
1. 内部存储(存储位置为机身内存)
2. 外部存储(存储位置为sd卡中)
三、数据库
四、网络
】
【
存储特点:
1. 以键值对的特点存储数据
2. 存储位置固定:data/data/程序包名/shared_prefs
3. 存储的文件类型(文件后缀)固定: xml文件
4. 存储的数据类型固定,只能是:boolean,float,int,long,String,Set
实现方式:
存储:
1. 创建一个SharedPreferences对象
2. 通过pref对象获取Editor对象,通过该对象调用存储数据的方法
3. 通过Editor对象调用put方法存入数据
4. 通过commit或者apply方法进行提交,否则数据存不进去
5. //1. 创建一个SharedPreferences对象
6. /*
7. * 可以通过getSharedPreferences方法或者getPreferences方法
8. * 获取对象
9. * 区别在于:getPreferences方法无法自定义文件名
10. * getSharedPreferences方法参数:
11. * 1. 自定义文件名
12. * 2. 存储的文件类型,如,只读,只写,私有等
13. *
14. * */
15. SharedPreferencespref = getSharedPreferences("ay.txt", Context.MODE_PRIVATE);
16.
17. //2. 通过pref对象获取Editor对象,通过该对象调用存储数据的方法
18. Editoredit = pref.edit();
19.
20. //3. 通过Editor对象调用put方法存入数据
21. edit.putBoolean("bool", true);
22. edit.putString("str", "llalalla");
23.
24. Set
25. set.add("abc");
26. set.add("bcd");
27. set.add("eee");
28.
29. edit.putStringSet("set", set);
30.
31. //4. 通过commit或者apply方法进行提交,否则数据存不进去
32. /*
33. * 区别:commit是在主线程中存入数据
34. * apply是异步存入数据,即在子线程中存入数据
35. * */
36. edit.commit();
读取:
1. 创建一个SharedPreferences对象
2. 通过pref对象调用get方法取出数据
//1.创建一个SharedPreferences对象
SharedPreferences pref1 = getSharedPreferences("ay.txt", Context.MODE_PRIVATE);
//2. 通过pref对象调用get方法取出数据
/*
* 参数一:
* 要读取的数据在键值对中对应的key
* 参数二:
* 默认值,当文件不存在或者key写错时,getBoolean方法的返回值为此默认值
* */
boolean b = pref1.getBoolean("bool", false);
String s = pref1.getString("str", "moren");
Set
Log.i("===", "!!! "+b+" "+s+" "+ss.toString());
注:当通过SharedPreferences对象存入和读取数据时,可以使用同一个SharedPreferences对象同时执行存入和读取操作
】
【
public class WelcomeActivity extends Activity {
private SharedPreferences pref ;
/*
* 只有当程序第一次运行时显示的引导页面
*
* 实现思路:
* 判断是否是第一次登录
* 如果是,正常显示本页面,如果不是,直接由本页面跳转到下一个页面
* */
@Override
protected voidonCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
pref =getSharedPreferences("login", MODE_PRIVATE);
boolean flag = pref.getBoolean("key", false);
if(flag){ //有原始存入的值就不是第一次登录
startActivity(new Intent(WelcomeActivity.this,MainActivity.class));
finish();
}
setContentView(R.layout.welcome);
}
public voidclick(View v){
pref.edit().putBoolean("key",true).commit();
startActivity(new Intent(WelcomeActivity.this,MainActivity.class));
finish();
}
}
public class MainActivity extends Activity {
/*
* 实现记住用户功能
**/
private EditText name,pass;
private Button but;
private CheckBox cb;
boolean flag;
private SharedPreferences pref;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pref = getSharedPreferences("name", Context.MODE_PRIVATE);
initView();
//初始化情况下决定是否要显示用户名
Stringss = pref.getString("user",null);
if(ss != null){
name.setText(ss);
cb.setChecked(true);
}
}
private voidinitView() {
// TODO Auto-generated method stub
name =(EditText) this.findViewById(R.id.editText1_xe);
pass =(EditText) this.findViewById(R.id.editText2_xe);
cb=(CheckBox) this.findViewById(R.id.checkBox1_xe);
but=(Button) this.findViewById(R.id.button2_xe);
}
public voidclick(View v){
switch (v.getId()) {
case R.id.button1_xe: //登录
if(cb.isChecked()){
Strings = name.getText().toString();
pref.edit().putString("user",s).commit();
}else{
pref.edit().clear().commit();
}
finish();
break;
case R.id.button2_xe://控制密码的显示与隐藏
if(flag){
//显示密码操作
flag = false;
pass.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
but.setText("显示密码");
}else{
flag= true;
pass.setTransformationMethod(PasswordTransformationMethod.getInstance());
but.setText("显示密码");
}
break;
}
}
}
】
【
共同特点:
存入数据,读取数据时使用IO流进行的操作
】
【
1. 存储位置固定:data/data/程序包名/files
2. 存储的文件类型可任意指定
3. 存储的数据类型不固定,可以存储任意的图片,文字等数据
实现步骤:
存入:
1. 获取用于写入数据的Output流对象
2. 通过流对象调用write方法写入数据
3. 关闭流对象
//1.获取用于写入数据的Output流对象
/*
* 参数一:指定生成的文件名称,
* 二:文件的类型
* */
os = openFileOutput("ay.txt", Context.MODE_APPEND);
//2. 通过流对象调用write方法写入数据
os.write("多卡佛肚佛IDUFO萨迪UFOis度覅偶爱哦福".getBytes());
//3.关闭流对象
os.close();
读取:
1. 获取用于读取数据的Input流对象
2. 通过流对象的read方法读取数据
3. 关闭流对象
//1.获取用于读取数据的Input流对象
InputStream is = openFileInput("ay.txt");
//2. 通过流对象的read方法读取数据
byte[] by =new byte[1024];
int num=0;
StringBuilder builder = new StringBuilder();
while ((num = is.read(by)) != -1) {
builder.append(new String(by,0,num));
}
Log.i("===", "-====getString "+builder.toString());
//3. 关闭流对象
is.close();
】
【
public class MainActivity extends Activity {
private ImageView img_read_n;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
img_read_n = (ImageView) this.findViewById(R.id.img_read_n);
}
public voidclick(View v) {
switch (v.getId()) {
case R.id.btn_n_cun:// 向机身内存中存储文件数据
storyFile();
break;
case R.id.btn_n_du:// 读取机身内存中指定的文件
readFile();
break;
case R.id.btn_n_drin:// 将drawable文件夹中的图片存入本地
storeDrawableInFile();
break;
case R.id.btn_n_drread:// 读取机身内存中的图片
readDrawableInFile();
break;
}
}
/**
* 读取机身内存中的图片
*/
private voidreadDrawableInFile() {
// 读取并显示机身内存中图片的方式一:
/*
* InputStream is = null ; try { is=openFileInput("dr.jpg");
*img_read_n.setImageBitmap(BitmapFactory.decodeStream(is)); }
* catch (FileNotFoundException e) { // TODO Auto-generated catch
* block e.printStackTrace(); }finally{ if(is!= null){ try {
* is.close(); is =null; } catch (IOExceptione) { // TODO
* Auto-generated catch blocke.printStackTrace(); } } }
*/
// 读取并显示机身内存中图片的方式二:
img_read_n.setImageURI(Uri.parse("file://"
+getFilesDir().getAbsolutePath() + "/dr.jpg"));
}
/**
* 将drawable文件夹中的图片存入本地
*/
private voidstoreDrawableInFile() {
/*
* compress 压缩方法作用:将bit图片中的数据压缩写入到参数三指定的流中
*/
Bitmap bit = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher);
OutputStream oo = null;
try {
oo = openFileOutput("dr.jpg", Context.MODE_PRIVATE);
/*
* 1. 图片的解析格式 2. 生成的图片的质量,范围0到100,质量越高,图片越清晰但是此质量值对解析格式为png的无效
*/
bit.compress(CompressFormat.JPEG, 20, oo);
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (oo != null){
try {
oo.close();
oo= null;
}catch (IOException e) {
// TODOAuto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 读取机身内存中指定的文件
*/
private voidreadFile() {
FileInputStreamfis = null;
try {
fis= openFileInput("xys.txt");
byte[] buf = newbyte[1024];
int num = 0;
StringBufferbuffer = new StringBuffer();
while ((num = fis.read(buf)) != -1) {
buffer.append(new String(buf, 0, num));
}
Toast.makeText(this, buffer.toString(), Toast.LENGTH_SHORT)
.show();
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (fis != null){
try {
fis.close();
fis= null;
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
* 向机身内存中存储文件数据
*/
private voidstoryFile() {
FileOutputStreamout = null;
try {
out= openFileOutput("xys.txt",Context.MODE_PRIVATE);
out.write("的附件见客户的关键是开发教科书的反馈见多识广".getBytes());
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (out != null){
try {
out.close();
out= null;
}catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
】
【
1. 存储位置部分固定:手机的外部存储卡,sd卡中, 默认的sd路径: /mnt/sdcard
2. 存储的文件类型可任意指定
3. 存储的数据类型不固定,可以存储任意的图片,文字等数据
实现方式:
存入:
通过指定sd卡文件路径写获取对应的FileOutputStream写入数据即可
FileOutputStreamfos = new FileOutputStream("/mnt/sdcard/aa.txt");
读取:
通过指定的文件路径获取对应FileInputStream读取数据即可
FileInputStream fis = newFileInputStream("/mnt/sdcard/aa.txt");
Sd卡中常用的操作方法:
获取SD卡的状态:Environment.getExternalStorageState()
获取SD卡的根路径:Environment.getExternalStorageDirectory()
访问特定类型的目录:Environment.getExternalStoragePublicDirectory(String type)
DIRECTORY_ALARMS // 警报的铃声
DIRECTORY_DCIM // 相机拍摄的图片和视频保存的位置
DIRECTORY_DOWNLOADS // 下载文件保存的位置
DIRECTORY_MOVIES // 电影保存的位置, 比如 通过google play下载的电影
DIRECTORY_MUSIC // 音乐保存的位置
DIRECTORY_NOTIFICATIONS // 通知音保存的位置
DIRECTORY_PICTURES // 下载的图片保存的位置
DIRECTORY_PODCASTS // 用于保存podcast(博客)的音频文件
DIRECTORY_RINGTONES // 保存铃声的位置
访问内存状态
StatFs:文件内存状态类
示例代码
// 获取SD卡根目录
File path =Environment.getExternalStorageDirectory();
// 获取指定目录下的内存存储状态
StatFs stat =new StatFs(path.getPath());
// 获取单个扇区的大小
long blockSize= stat.getBlockSize();
// 获取扇区的数量
longtotalBlocks = stat.getBlockCount();
// 获取可以使用的扇区数量
longavailableBlocks = stat.getAvailableBlocks();
// 可用空间 = 扇区的大小 + 可用的扇区
longavailableSize = blockSize * availableBlocks;
// 总空间 = 扇区的总数 * 扇区的大小
long totalSize= blockSize * totalBlocks;
// 格式化文件大小的格式
Log.i("oye","可用空间 = " + Formatter.formatFileSize(this, availableSize));
Log.i("oye","总空间 = " + Formatter.formatFileSize(this, totalSize));
注意:操作SDCard需要添加权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
】