概述

在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: 结束

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

记录学习,记录成长!

转载于:https://www.cnblogs.com/hsiang/p/10645965.html

一起学Android之Storage相关推荐

  1. 菜鸟学Android源码——Setting(1)

    菜鸟学Android源码--Setting(1) 在上一篇中,我简单介绍了Android源码的下载和编译,还没有下载编译源码的小伙伴请看这里:Android源码分析之--下载并编译源码 关于系统设置A ...

  2. Carson带你学Android:最全面的Webview使用详解

    前言 现在很多App里都内置了Web网页(Hyprid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 那么这种该如何实现呢?其实这是Android里一个叫WebView的组件实现的.今 ...

  3. 从零开始学android编程_android初学者的入门秘籍

    大概是去年年底开始接触android 原本是学习嵌入式的我,领导让我看看能不能搞一下这个android APP. 一开始的我懵逼得很... 这android APP 不是得用java写吗??? 现在我 ...

  4. 做嵌入式的必须学Android吗

    做嵌入式的必须学Android吗 Android方向适合哪些人呢?适合那些已经在自己领域有了一定的工作经验的人,适合作为自己的拓展,适合提升自己的能力,譬如说已经做三年Linux驱动,就可以尝试拓展去 ...

  5. 教我兄弟学Android逆向

    作者论坛****账号:会飞的丑小鸭 课程导航: <教我兄弟学Android逆向01 编写第一个Android程序> <教我兄弟学Android逆向02 破解第一个Android程序 ...

  6. Carson带你学Android:你要的WebView与 JS 交互方式都在这里了

    前言 现在很多App里都内置了Web网页(Hybrid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 上述功能是由Android的WebView实现的,其中涉及到Android客户端与 ...

  7. Carson带你学Android:请收好这一份全面详细的Android学习指南

    前言 如果你也学习Android,那么你大概率会看过我的文章.经常有读者给我留言:"该怎么学习Android?"."日常学习Android的方法是什么". 今天 ...

  8. Carson带你学Android:源码解析自定义View Draw过程

    前言 自定义View是Android开发者必须了解的基础 网上有大量关于自定义View原理的文章,但存在一些问题:内容不全.思路不清晰.无源码分析.简单问题复杂化 等 今天,我将全面总结自定义View ...

  9. 第88章、系统服务之NOTIFICATION_SERVICE服务(从零开始学Android)

    Notification通知将一个图标(包含一条可选的提示文本信息)填加到系统的状态栏(一般来说,Android手机的状态栏是在顶部,非底部,要注意噢)中,并将一条展开信息添加到通知窗口中.当用户选中 ...

  10. Carson带你学Android:这是一份全面详细的属性动画学习攻略!

    前言 属性动画的使用 是 Android 开发中常用的知识 本文将献上一份全面 & 详细的属性动画学习指南,将详细介绍属性动画的所有内容,包括:意义.作用.应用场景.功原理 & 具体使 ...

最新文章

  1. 微信小程序去掉左上角的返回箭头
  2. 想在SqlDbHelper.cs类中加的垃圾方法
  3. 字符指针,字符数组,双引号的字符串的区别与联系
  4. Linux培训教程 Git在linux下的使用
  5. linux下缓存命中测试,linux为什么报表缓存缓存未命中?_linux_开发99编程知识库...
  6. P5341-[TJOI2019]甲苯先生和大中锋的字符串【SAM】
  7. 我的YUV播放器MFC小笔记:添加删除自定义分辨率
  8. 如何使用IEDA连接数据库
  9. Android设计模式系列-组合模式
  10. 《JavaScript高级程序设计》笔记之'ECMAScript基础'
  11. Confluence或JIRA验证码乱码的问题
  12. [原创]Linux系统启动过程分析
  13. Godot—2D游戏设计笔记
  14. 毕业设计 - 基于JAVA的小区/园区停车管理系统(简便易上手)
  15. What is Dymola?---Dymola的特点和架构
  16. 一场会带来啥改变?三翼鸟引领行业进入有脑时代
  17. 总结:OSI七层协议
  18. 联邦学习:加密算法Paillier,Affine,IterativeAffine
  19. 【华为电脑管家】打开多屏协同会自动修改微软拼音输入法兼容性的解决方案
  20. 使用fail2ban解决暴力破解问题

热门文章

  1. Volley源码解析(三)
  2. Android context.getSystemService的简单说明
  3. 新场景 + 新应用,Flink 在机器学习领域的生产落地
  4. 我与潘家园金爷的对话
  5. 你的努力,是否符合你的预期?
  6. FFmpeg在Linux下安装编译过程
  7. 通过一个工具类更深入理解动态代理和Threadlocal
  8. android内存泄漏MAT,利用Android Studio、MAT对Android进行内存泄漏检测
  9. 编写python程序、找出100_100+ Python挑战性编程练习(1)
  10. python通过什么对象连接数据库_介绍Python 数据库的Connection、Cursor两大对象