安卓的存储机制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓的存储机制相关的知识,希望对你有一定的参考价值。

参考技术A 安卓的文件存储分为内部存储和外部存储,在安卓早期,手机内置存储很小,都是用于应用的私有存储空间,外部存储就是sdcard。往后发展,手机的内置存储越来越大,同时也出现了一些不支持sdcard的手机。如今安卓的外部存储已经不限于sdcard了。

内部存储

手机内部存储除了放置应用的私有和系统空间以外都为外部存储,内部存储空间有限。对于设备中每一个安装的 App,系统都会在内部存储空间的 data/data 目录下以应用包名为名字自动创建与之对应的文件夹。这个文件夹用于 App 中的 WebView 缓存页面信息,SharedPreferences 和 SQLiteDatabase 持久化应用相关数据等。

内部存储包含的文件

外部存储

在安卓文件的外部存储部分又分为了应用的私有目录和共有目录。

私有目录

外部的存储的私有目录地址可以根据context的相应方法得到。

公共目录

外部的存储的公有目录可以根据Environment的相应方法得到。

创建文件测试

通过file创建data文件

Test 1

Filefile = newFile("data");

try

//新建文件

booleanbl=file.createNewFile();

//判断文件创建是否成功

Log.d("myTag","onCreate:"+bl);

catch(IOExceptione)

e.printStackTrace();



运行结果

文件创建失败

同时文件夹中没有出现该文件

猜测创建失败问题来自文件地址的问题

Test 2

Filefile=null;

file=newFile(getCacheDir()+"data");

try

//新建文件

booleanbl=file.createNewFile();

//判断文件创建是否成功

Log.d("myTag","onCreate:"+bl);

catch(IOExceptione)

e.printStackTrace();



运行结果

文件创建成功,同时在/data/data/com.example.myapplication的地址处生成了名为cachedata的文件

文件名与预期不同

Test 3

Filefile=null;

file=newFile(getFilesDir()+"data");

try

//新建文件

booleanbl=file.createNewFile();

//判断文件创建是否成功

Log.d("myTag","onCreate:"+bl);

catch(IOExceptione)

e.printStackTrace();



运行结果

创建了一个files文件夹及一个filesdata文件

filesdata文件位置:/data/data/com.example.myapplication/filesdata

Test 4

Filefile=null;

file=newFile(getCodeCacheDir()+"data");

try

//新建文件

booleanbl=file.createNewFile();

//判断文件创建是否成功

Log.d("myTag","onCreate:"+bl);

catch(IOExceptione)

e.printStackTrace();



运行结果

code_cachedata地址:/data/data/com.example.myapplication/code_cachedata

Test 5

Filefile=null;

file=newFile(getCacheDir().getPath(),"data");

try

//新建文件

booleanbl=file.createNewFile();

//判断文件创建是否成功

Log.d("myTag","onCreate:"+bl);

catch(IOExceptione)

e.printStackTrace();



运行结果

成功在cache文件下创建data文件

总结使用file类创建文件时需要详细的地址,这里的地址可以通过context的getcacheDir()等方法得到

使用openFileinputStream创建

FileInputStreaminputStream=null;

try

inputStream=openFileInput("data");

catch(FileNotFoundExceptione)

e.printStackTrace();

finally

try

inputStream.close();

catch(IOExceptione)

e.printStackTrace();



新建了一个文件夹而没有新建文件

将输入流改为输出流后

FileOutputStreamoutputStream=null;

try

outputStream=openFileOutput("data",MODE_PRIVATE);

catch(FileNotFoundExceptione)

e.printStackTrace();

finally

try

outputStream.close();

catch(IOExceptione)

e.printStackTrace();



成功创建文件

使用openfilexxxxstream在只输入文件名进行创建文件时会默认在data/data/包名/files处创建文件,若不存在files文件则会新建一个files文件

File file = new File();

方法会读取该文件地址的文件,如果没有也不会报错。

file.createNewFile();

会向该地址创建一个文件,返回一个bool值以判断是否创建成功

openFileInputstream/openFileOutputstream都只能操作data/data/包名 处的文件

Tast 6

Filefile;

file=newFile(getExternalCacheDir(),"data");

try

booleanbl=file.createNewFile();

Log.d("myTag","onCreate:"+bl);

catch(IOExceptione)

e.printStackTrace();



需要读写公共空间操作有所区别

Filefile;

file=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

FilemFile;

mFile=newFile(file,"data");

try

booleanbl=mFile.createNewFile();

Log.d("myTag","onCreate:"+bl);

catch(IOExceptione)

e.printStackTrace();



需要申明读写权限对于android6.0以上还需要动态申请权限

<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

<uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/>

最后附上安卓所有文件存储的地址的获取方法

Android 安卓告别SharedPreFerences,你好MMKV


你好 MMKV!

在这里插入图片描述

MMKV是腾讯开源的轻量级持久化存储框架,相比于传统的SharedPreFerences(以下简称SP),优点有很多

  1. MMKV有更好的锁机制来保证数据的完整,而SP的跨进程和apply机制会导致数据的丢失
  2. SP是全量更新,也正因如此,它的时间开销更大,MMKV存储是mmap,无需全量写入
  3. MMKV同时也能够直接导入SP中的数据
  4. 使用MMKV能够更好的避免程序ANR

为什么要使用 MMKV

使用SP低性能导致程序ANR,commit 和 apply 均可能会造成ANR,这也是Android工程师最为痛恨的大病之一,所以使用MMKV可以避免此问题,使得自己心情舒畅!从下图看出MMKV与SP的读写耗时对比,MMKV也是毫不逊色的!

(下面这一个图是我自己写的代码测试所得到的)
我写的代码测试

MMKV Github给出的:
Writing random int for 10000 times, we get this chart:
写入随机Int值10000次所得到的图表
MMKV Github统计图


代码使用

来实操一下,看看MMKV耐不耐操


引入

dependencies {
    implementation 'com.tencent:mmkv-static:1.2.9'
}

最简单的代码栗子

1、在Application初始化

MMKV.initialize(this)//会返回MMVK存储的目录(String)

2、创建MMKV,可以通过 defaultMMKV() 来创建,这个是全局默认的;也可以通过 mmkvWithID() 对应自己业务来创建,如下:

val mmkv = MMKV.defaultMMKV()
val mmkv = MMKV.mmkvWithID("mmapID")

3、数据写入,可以写入Int,String,Boolean,Long,Float,Double类型的数据,只需要调用 encode() 方法写入数据,会根据数据类型进行重载。

//写入Int
mmkv.encode("keyName1", 123)

//写入String
mmkv.encode("keyName2", "Text")

//写入Boolean
mmkv.encode("keyName3", true)

//写入Long
mmkv.encode("keyName4", 123L)

...

4、数据读取,通过 decode 来进行读取

//读取key为keyName1的Int类型数据
mmkv.decodeInt("keyName1")

//读取key为keyName1的Int类型数据,如果对应key的值不存在,会返回默认值123
mmkv.decodeInt("keyName1",123)

//读取key为keyName2的String类型数据,如果对应key的值不存在,会返回null,建议用下一个
mmkv.decodeString("keyName2")

//读取key为keyName2的String类型数据,如果对应key的值不存在,会返回默认字符串:defaultValue
mmkv.decodeString("keyName2", "defaultValue")

//不再举例,Boolean,Long,Float,Double参考以上使用


GitHub

MMKV:https://github.com/Tencent/MMKV

以上是关于安卓的存储机制的主要内容,如果未能解决你的问题,请参考以下文章

移动端安全 - 安卓Android - 漏洞修复方案整理

数据存储

安卓内部外部文件存储

安卓 11 |范围存储实施

安卓内外部存储完全解析 -- 别再弄混了

Android 安卓告别SharedPreFerences,你好MMKV