一起学Android之Storage
概述
在android开发中,存储(storage)的方式根据具体的需求不同而不同,例如数据对应用程序是私有的还是其他应用程序(和用户)可以访问的,以及保存数据需要多大的空间。
存储分类
主要的存储方式有以下几种(本文主要涉及前三种):
- shared preferences:以键值对( key-value pairs)的方式存储在程序内部;
- internal storage:将数据保存在设备内存中;
- external storage:将公有数据保存在外部存储中(sd卡);
- sqlite databases:保存结构化数据到私有数据库中;
- network connection:通过网络服务器,将数据存储在web上。
涉及知识点
涉及的知识点如下:
- sharedpreferences 共享目录接口,通过context中的getsharedpreferences进行实例化。
- sharedpreferences.editor 共享目录编辑器,需要以commit进行保存。
- fileoutputstream 文件输出流,用write方法将数据保存文件。
- fileinputstream 文件输入流,用于读取文件的内容,通过context中的openfileinput进行实例化,用read方法进行读取内容。
- deletefile context中的方法,删除指定路径的文件
- environment.getexternalstoragedirectory() 获取外部存储的根目录。
- environment.getexternalstoragestate() 获取外部存储卡的状态。
- file.separator 文件路径分割符,用斜杠(/)进行表示。
- bitmapfactory.decoderesource(getresources(), r.drawable.bg) 通过资源文件实例化对象。
- bitmapfactory.decodefile(imgfile.getabsolutepath() 通过具体文件的路径实例化对象。
- 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: 结束
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
记录学习,记录成长!
上一篇: 华为Mate40系列售价公布