安卓的(持久化)存储机制:
1.共享参数存储SharedPreferences,一遍用于存储简单的键值对的配置信息,用户名....
键值对的值限于int,long,String,float,boolean
2.内部存储Internal Storage,即存在手机的内存中.一遍用于存放一下不太大的文件.
手机存储:
RAM:运行时内存.相当于pc机的内存,不是持久化存储的,里面的数据断点就消失.
ROM:相当于pc机的硬盘
SD CARD:扩展存储卡.
SharedPreferences共享参数
一、数据存储选项:Data Storage ——Storage Options
1、Shared Preferences
Store private primitive data in key-value pairs.
保存简单的键值对数据。
2、Internal Storage
Store private data on the device memory.
在手机内存中保存不对外共享的信息。
3、External Storage
Store public data on the shared external storage.
在外部存储设备上保存公共的数据信息。主要指保存在SDCard上。
4、SQLite Databases
Store structured data in a private database.
将结构化的数据保存进数据库。
二、SharedPreferences:
(一)、概念:
SharedPreferences是Android系统提供的一个通用的数据持久化框架,用于存储和读取
key-value
类型的原始基本数据类型的数据,目前支持
String、int、long、float、boolean
等基本类型的存储,对于自定义的对象数据类型,无法使用SharedPreferences来存储。
SharedPreferences主要用于存储系统的配置信息。例如上次登录的用户名,上次最后设置的配置信息(如:是否打开音效、是否使用振动,小游戏的玩家积分等)。当再次启动程序后依然保持原有设置。SharedPreferences用键值对方式存储,方便写入和读取。
(二)、使用SharedPreferences的步骤:
1、获取SharedPreferences对象;
SharedPreferences本身是一个接口,无法直接创建实例,通过
Context
中定义的实例方法
getSharedPreferences
(String name, int mode)方法来获取实例。
该方法的第二个参数表示
文件读写的操作模式,传入:
Context.
MODE_PRIVATE
: 指定该SharedPreferences的数据只能被本应用程序读、写;
2、调用edit()方法获取
SharedPreferences.Editor接口类型的对象
;
3、通过SharedPreferences.Editor接口提供的
putXxx
(...)方法对SharedPreferences进行更新;
4、调用SharedPreferences.Editor的
commit
()方法,将更新提交到SharedPreferences中。
clear
()方法,清空已有的所有共享参数,但不清除editor里面的数据(在commit()之后能写出去)
5、调用SharedPreferences的getXxx(String key,Xxx defaultValue)方法获取指定key的value
SharedPreferences的其他常用方法:
boolean contains(String key)判断是否包含指定键的数据
Map<String,?> getAll()获取所有的键值对, 需要对象造型: Map<String,Object> map = (Map<String,Object>)sp.getAll();
核心代码:
核心代码:
public void click(View v) {
if (v.getId() == R.id.bt_save) {// 保存共享参数
//要保存,必须先获取Editor对象
Editor editor = sp.edit();
// editor.putString("name", et_name.getText().toString());
// editor.putString("phone", et_phone.getText().toString());
editor.putString("test", "aaaaaaaaa");
editor.clear();//清空已有的所有共享参数,再把editor里面的数据写出去
editor.commit();//提交
Toast.makeText(this, "保存成功!", 0).show();
} else { // 读取共享参数
// String name = sp.getString("name", "默认 值-无名氏");
// String phone = sp.getString("phone", "000000");
// tv_showData.setText("name:"+name+",phone:"+phone);
Map<String,?> map = sp.getAll();
Set<String> keys = map.keySet();
StringBuilder sb = new StringBuilder();
for(String aKey :keys){
Object obj = map.get(aKey);
sb.append(aKey).append("=").append(obj).append('\t');
}
tv_showData.setText(sb);
}
}
(四)、保存之后的SharedPreferences数据文件:
SharedPreferences数据总是以xml格式保存在:
/data/data/包名/shared_prefs
/{文件名};
Cd D:\workspace\sdk\platform-tools------------adb所在的目录
adb shell
cd
/data/data/包名/shared_prefs
ls 查看所有的目录
cat person.xml
文件格式如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="pwd">123456</string>
<string name="username">xiangjun</string>
<int name="age">20</int>
</map>
------------------------------------------------------------------
内部存储Internal Storage
文件存储路径:
/data/data/包名/files/{文件名}
Context的实例方法(Activity中继承过来了):
FileOutputStream
openFileOutput
(String filename, int mode)//用追加或覆盖的模式, 获得文件输出流, 可以写出到指定文件名的文件
mode的取值:
Context.MODE_APPEND追加模式,不写就是覆盖模式
Context.MODE_PRIVATE
中间可以用 | 或者 + 来连接
十进制12===>二进制00000000000001100
十进制5 ===>二进制00000000000000101
int k = 12&5; //4
int m = 12|5; //13
i:二进制00000000000001000
j:二进制00000000000000100
int k = i | j;//12
int m = i+j;//12
Context的实例方法:
FileInputStream
openFileInput
(String filename) 该方法应写在事件处理方法里面
String[]
fileList
()列出所有的文件名数组
boolean
deleteFile
(String filename)删除指定文件名的文件
[ 案例:]
点击按钮A从UI上获取用户名和手机号,保存到内部存储的文件中;
点击按钮B从内部存储中取出显示在文本框中
----------------------------------------------------
External Storage之SDCard操作:
(一)、引入:
毕竟手机内置存储空间很有限, 内存卡中可能空间不够,为了更好地存储应用程序的大文件数据,需要读写SD卡上的文件。SD卡大大扩充了手机的存储能力。
(二)、读写SD卡的步骤:
1、先判断手机是否有sd卡:
调用
Environment
的静态方法 String
getExternalStorage
State
()方法判断手机是否插上sdcard。得到的结果可能有:
Environment.
MEDIA_MOUNTED
介质已加载完
Environment.MEDIA_MOUNTED_READ_ONLY 介质已加载完,但是只读状态
Environment.MEDIA_CHECKING 正在检测介质
Environment.MEDIA_UNKNOWN 介质未知
Environment.MEDIA_UNMOUNTED 介质已卸载
2、获取sdcard的路径;
调用
Environment
的
静态方法String
getExternalStorage
Directory
()方法来获取外部存储器的目录。
3、此外还可以获取SDCard可用磁盘空间的大小(借助
StatFs
类来实现);
4、清单文件中设置读写sdcard的权限;
<uses-permission android:name="android.permission.
MOUNT_UNMOUNT_FILESYSTEMS
"/> 允许挂载和反挂载文件系统可移动存储
<uses-permission android:name="android.permission.
WRITE_EXTERNAL_STORAGE
"/>
<uses-permission android:name="android.permission.
READ_EXTERNAL_STORAGE
" />
5、执行读写操作(基本IO流操作)。
(三)、封装SDCard的工具类:SDCardHelper类
l
判断sdcard是否挂载
boolean isSDCardMounted()
getExternalStorageState()
Environment.MEDIA_MOUNTED
l
获取sdcard绝对物理路径
String getSDCardPath()
getExternalStorageDirectory()
l
获取sdcard的全部的空间大小。返回MB字节
long getSDCardSize()
new StatFs(
getSDCardPath
());
sf.getBlockSize();//获取每块的大小
sf.
getBlockCount();//获取总块数
l
获取sdcard的剩余空间的大小。返回MB字节
long getSDCardFreeSize()
sf.
getFreeBlocks();//获取空闲的块数
l
获取SD卡的可用空间大小,返回MB
long getSDCardAvailableSize()
sf.
getAvailableBlocks();//获取可用空间的大小
l
将文件(byte[])保存进sdcard指定的路径下 dir:指定的路径
boolean saveFileToSDCard(byte[] data, String dir,String filename)
l
已知文件的
绝对路径
,从sdcard中获取到该文件,返回byte[].
byte[] loadFileFromSDCard(String filepath)
public class SDCardHelper {
private static String TAG = "SDCardHelper";
/**
* 判断sdcard是否挂载
*/
public static boolean isSDCardMounted() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
/**
* 获取sdcard绝对物理路径 得到的格式为 /storage/sdcard 后面没有斜线
*/
public static String getSDCardPath() {
if (isSDCardMounted()) {
return Environment.getExternalStorageDirectory().getAbsolutePath();
} else {
return null;
}
}
/**
* 获取sdcard的全部的空间大小。返回MB字节
*/
public static long getSDCardSize() {
if (isSDCardMounted()) {
StatFs fs = new StatFs(getSDCardPath());
// 因为带有Long结尾的替代方法需要API 18以上的SDK才能支持,所以,暂时使用旧的
long size = fs.getBlockSize();
long count = fs.getBlockCount();// 获取总块数
return size * count / 1024 / 1024;
}
return 0;
}
/**
* 获取sdcard的剩余空间的大小。返回MB字节
*/
public static long getSDCardFreeSize() {
if (isSDCardMounted()) {
StatFs fs = new StatFs(getSDCardPath());
long size = fs.getBlockSize();
long count = fs.getFreeBlocks();// 获取空闲的块数
return size * count / 1024 / 1024;
}
return 0;
}
/**
* 获取SD卡的可用空间大小,返回MB
*
* @return
*/
public static long getSDCardAvailableSize() {
if (isSDCardMounted()) {
StatFs fs = new StatFs(getSDCardPath());
int count = fs.getAvailableBlocks();// 获取可用空间的大小
int size = fs.getBlockSize();
return count * size / 1024 / 1024;
}
return 0;
}
/**
* 将文件(byte[])保存进sdcard指定的路径下 dir:指定的路径
*/
public static boolean saveFileToSDCard(byte[] data, String dir, String filename) {
BufferedOutputStream bos = null;
if (isSDCardMounted()) {
Log.i(TAG, "==isSDCardMounted==TRUE");
File file = new File(getSDCardPath() + File.separator + dir);
Log.i(TAG, "==file:" + file.toString() + file.exists());
if (!file.exists()) {
boolean flags = file.mkdirs();
Log.i(TAG, "==创建文件夹:" + flags);
}
try {
bos = new BufferedOutputStream(new FileOutputStream(new File(file, filename)));
bos.write(data, 0, data.length);
bos.flush();
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
/**
* 已知文件的绝对路径,从sdcard中获取到该文件,返回byte[]
*/
public static byte[] loadFileFromSDCard(String filepath) {
BufferedInputStream bis = null;
ByteArrayOutputStream baos = null;
if (isSDCardMounted()) {
File file = new File(filepath);
if (file.exists()) {
try {
baos = new ByteArrayOutputStream();
bis = new BufferedInputStream(new FileInputStream(file));
byte[] buffer = new byte[1024 * 8];
int c = 0;
while ((c = bis.read(buffer)) != -1) {
baos.write(buffer, 0, c);
baos.flush();
}
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bis != null) {
bis.close();
baos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return null;
}
}