• 一起学Android之Storage


    概述

    在Android开发中,存储(Storage)的方式根据具体的需求不同而不同,例如数据对应用程序是私有的还是其他应用程序(和用户)可以访问的,以及保存数据需要多大的空间。

    存储分类

    主要的存储方式有以下几种(本文主要涉及前三种):

    1. Shared Preferences:以键值对( key-value pairs)的方式存储在程序内部;
    2. Internal Storage:将数据保存在设备内存中;
    3. External Storage:将公有数据保存在外部存储中(SD卡);
    4. SQLite Databases:保存结构化数据到私有数据库中;
    5. Network Connection:通过网络服务器,将数据存储在web上。

    涉及知识点

    涉及的知识点如下:

    1. SharedPreferences 共享目录接口,通过Context中的getSharedPreferences进行实例化。
    2. SharedPreferences.Editor 共享目录编辑器,需要以commit进行保存。
    3. FileOutputStream 文件输出流,用write方法将数据保存文件。
    4. FileInputStream 文件输入流,用于读取文件的内容,通过Context中的openFileInput进行实例化,用read方法进行读取内容。
    5. deleteFile Context中的方法,删除指定路径的文件
    6. Environment.getExternalStorageDirectory() 获取外部存储的根目录。
    7. Environment.getExternalStorageState() 获取外部存储卡的状态。
    8. File.separator 文件路径分割符,用斜杠(/)进行表示。
    9. BitmapFactory.decodeResource(getResources(), R.drawable.bg) 通过资源文件实例化对象。
    10. BitmapFactory.decodeFile(imgFile.getAbsolutePath() 通过具体文件的路径实例化对象。
    11. File 文件对象,mkdirs() 创建多层目录 mkdirs创建单个目录,exists() 判断文件或目录是否存在,createNewFile() 创建新文件。

    Shared Preferences

    此种方式,只能保存简单的数据类型如下图所示:

    代码如下:

     1     /**
     2      * SharedPreferences保存
     3      * @param v
     4      */
     5     public void sharedSave(View v){
     6         String name=etName.getText().toString().trim();
     7         String age=etAge.getText().toString().trim();
     8         if(TextUtils.isEmpty(name)||TextUtils.isEmpty(age)){
     9             return;
    10         }
    11         //构造一个编辑器----笔
    12         SharedPreferences.Editor editor = sp.edit();
    13         //数据的存储---只能存储简单的数据
    14         editor.putString("name",name);
    15         editor.putString("age",age);
    16         //提交--保存
    17         editor.commit();
    18         //清空
    19         etName.setText("");
    20         etAge.setText("");
    21     }
    22 
    23     /**
    24      * SharedPreferences读取
    25      */
    26     public void sharedRedo(View v){
    27         String name=sp.getString("name","");
    28         String age=sp.getString("age","");
    29         etName.setText(name);
    30         etAge.setText(age);
    31     }

    Internal Storage

    将数据内容转换为字节的方式保存在文件中,如下图所示:

    代码如下:

     1     /**
     2      * 内部保存
     3      * @param v
     4      */
     5     public void internalSave(View v) {
     6         String name = etName.getText().toString().trim();
     7         String age = etAge.getText().toString().trim();
     8         if (TextUtils.isEmpty(name) || TextUtils.isEmpty(age)) {
     9             return;
    10         }
    11 
    12         try {
    13             String content = "这是我的姓名:" + name + "这是我的年龄:" + age;
    14             FileOutputStream fos = openFileOutput(sname, MODE_PRIVATE);
    15             fos.write(content.getBytes());
    16             fos.close();
    17             etName.setText("");
    18             etAge.setText("");
    19         } catch (IOException e) {
    20             e.printStackTrace();
    21         }
    22     }
    23 
    24     /**
    25      * 内部读取
    26      * @param v
    27      */
    28     public void internalRedo(View v) {
    29         try {
    30             FileInputStream fis = openFileInput(sname);
    31             byte[] buffer = new byte[fis.available()];
    32             fis.read(buffer);
    33             fis.close();
    34             String content = new String(buffer);
    35             Toast.makeText(this, content, Toast.LENGTH_SHORT).show();
    36         } catch (IOException e) {
    37             e.printStackTrace();
    38         }
    39     }
    40 
    41     /**
    42      * 删除文件
    43      * @param v
    44      */
    45     public void internalDel(View v){
    46         boolean del=deleteFile(sname);
    47         if(del){
    48             Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show();
    49         }else{
    50             Toast.makeText(this, "删除失败", Toast.LENGTH_SHORT).show();
    51         }
    52     }

    External Storage

    在外部存储中,需要在AndroidManifest.xml中配置相关的读写权限,如下所示:

    1   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"  />
    2     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    3     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

    保存在SD卡中,如下图所示:

    代码如下:

     1     /**
     2      * 外部存储
     3      * @param v
     4      */
     5     public void externalSave(View v) {
     6 
     7         try {
     8             Log.i(TAG, "externalSave: 开始");
     9             Bitmap img = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
    10             ByteArrayOutputStream bass = new ByteArrayOutputStream();
    11             img.compress(Bitmap.CompressFormat.JPEG, 100, bass);
    12             img.recycle();
    13             Log.i(TAG, "externalSave: saveImg");
    14             boolean saveOk = saveImg("dog.jpg", bass.toByteArray());
    15             Log.i(TAG, "externalSave: saveImg:"+saveOk);
    16             if (saveOk) {
    17                 Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show();
    18             }
    19             bass.close();
    20             Log.i(TAG, "externalSave: 结束");
    21         } catch (IOException e) {
    22             e.printStackTrace();
    23             Log.i(TAG, "externalSave: 异常"+e.getMessage());
    24         }
    25     }
    26 
    27     /**
    28      * 外部读取
    29      * @param v
    30      */
    31     public void externalRedo(View v) {
    32         if (!isMounted()) {
    33             return;
    34         }
    35         try {
    36             Bitmap img = readImg("dog.jpg");
    37             iv01.setImageBitmap(img);
    38         } catch (Exception e) {
    39             e.printStackTrace();
    40         }
    41     }
    42 
    43     private boolean saveImg(String fileName,byte[] data){
    44         Log.i(TAG, "saveImg: 开始");
    45         if(!isMounted()){
    46             Log.i(TAG, "saveImg: 挂载失败");
    47             return false;
    48         }
    49         Log.i(TAG, "saveImg: 路径:"+storedPath);
    50         File dir=new File(storedPath);
    51         if(!dir.exists()){
    52            boolean f= dir.mkdirs();
    53             if(f){
    54                 Log.i(TAG, "saveImg: 创建目录成功:"+storedPath);
    55             }else{
    56                 Log.i(TAG, "saveImg: 创建目录失败:"+storedPath);
    57             }
    58         }
    59         Log.i(TAG, "saveImg: 判断路径:ok");
    60         try {
    61             File file=new File(storedPath,fileName);
    62             if(file.exists()){
    63                 Log.i(TAG, "saveImg: 判断文件:1");
    64                 file.delete();
    65             }
    66             Log.i(TAG, "saveImg: 判断文件:2");
    67             file.createNewFile();
    68             Log.i(TAG, "saveImg: 判断文件:ok");
    69             FileOutputStream fos=new FileOutputStream(file);
    70             fos.write(data);
    71             fos.close();
    72             return true;
    73         } catch (IOException e) {
    74             e.printStackTrace();
    75             Log.i(TAG, "saveImg: 异常:"+e.getMessage());
    76             return false;
    77         }
    78     }
    79 
    80     public Bitmap readImg(String fileName){
    81         if(!isMounted()){
    82             return null;
    83         }
    84         File imgFile=new File(storedPath,fileName);
    85         if(imgFile.exists()){
    86             return BitmapFactory.decodeFile(imgFile.getAbsolutePath());
    87         }
    88         return null;
    89     }
    90 
    91     private  boolean isMounted(){
    92         String state=Environment.getExternalStorageState();
    93         return  state.equals(Environment.MEDIA_MOUNTED);
    94     }


    备注

    在进行外部存储时,如果默认关闭了APP的存储空间权限,没有前往设置开启应用权限,即使manifest中正常注册权限,该APP仍让无法读写文件。调试日志如下:

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------

    未开启App的存储权限
    04-02 21:21:59.173 30863-30863/com.hex.demostorage I/DemoStorage: externalSave: 开始
    04-02 21:21:59.407 30863-30863/com.hex.demostorage I/DemoStorage: externalSave: saveImg
    04-02 21:21:59.408 30863-30863/com.hex.demostorage I/DemoStorage: saveImg: 开始
    04-02 21:21:59.412 30863-30863/com.hex.demostorage I/DemoStorage: saveImg: 路径:/storage/emulated/0/hex/images
    04-02 21:21:59.412 30863-30863/com.hex.demostorage I/DemoStorage: saveImg: 判断路径:ok
    04-02 21:21:59.412 30863-30863/com.hex.demostorage I/DemoStorage: saveImg: 判断文件:2
    04-02 21:21:59.414 30863-30863/com.hex.demostorage I/DemoStorage: saveImg: 异常:No such file or directory
    04-02 21:21:59.414 30863-30863/com.hex.demostorage I/DemoStorage: externalSave: saveImg:false
    04-02 21:21:59.414 30863-30863/com.hex.demostorage I/DemoStorage: externalSave: 结束
    开启App的存储权限
    04-02 21:22:48.519 31306-31306/com.hex.demostorage I/DemoStorage: externalSave: 开始
    04-02 21:22:48.754 31306-31306/com.hex.demostorage I/DemoStorage: externalSave: saveImg
    04-02 21:22:48.755 31306-31306/com.hex.demostorage I/DemoStorage: saveImg: 开始
    04-02 21:22:48.759 31306-31306/com.hex.demostorage I/DemoStorage: saveImg: 路径:/storage/emulated/0/hex/images
    04-02 21:22:48.760 31306-31306/com.hex.demostorage I/DemoStorage: saveImg: 判断路径:ok
    04-02 21:22:48.760 31306-31306/com.hex.demostorage I/DemoStorage: saveImg: 判断文件:2
    04-02 21:22:48.761 31306-31306/com.hex.demostorage I/DemoStorage: saveImg: 判断文件:ok
    04-02 21:22:48.763 31306-31306/com.hex.demostorage I/DemoStorage: externalSave: saveImg:true
    04-02 21:22:48.787 31306-31306/com.hex.demostorage I/DemoStorage: externalSave: 结束

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------

    记录学习,记录成长!

  • 相关阅读:
    Django 用户认证(Auth)组件
    Django 中间件
    EFCore Map 2 entities to same table
    Prevent properties being loaded unless specifically requested
    AutoMapper Queryable Extensions
    What does Include() do in LINQ?
    SqlServer备份还原 出现操作系统错误 5(拒绝访问) 的解决方案
    When to use Include in EF? Not needed in projection?
    Evaluate: lim x → 0 [1/x^2 1/sin^2x] 高等数学
    AutoMapper Explicit expansion
  • 原文地址:https://www.cnblogs.com/hsiang/p/10645965.html
Copyright © 2020-2023  润新知