Android的存储----重新认识Android(9)

安卓的(持久化)存储机制:
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类
判断sdcard是否挂载
boolean isSDCardMounted()
    getExternalStorageState()
    Environment.MEDIA_MOUNTED
获取sdcard绝对物理路径
String getSDCardPath()
    getExternalStorageDirectory()
获取sdcard的全部的空间大小。返回MB字节
long getSDCardSize()   
    new StatFs( getSDCardPath ());
    sf.getBlockSize();//获取每块的大小
     sf. getBlockCount();//获取总块数
获取sdcard的剩余空间的大小。返回MB字节
long getSDCardFreeSize()
     sf. getFreeBlocks();//获取空闲的块数
获取SD卡的可用空间大小,返回MB
long getSDCardAvailableSize()
     sf. getAvailableBlocks();//获取可用空间的大小
将文件(byte[])保存进sdcard指定的路径下  dir:指定的路径
boolean saveFileToSDCard(byte[] data, String dir,String filename)  
已知文件的 绝对路径 ,从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;
    }
    
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值