1.SharedPreferences数据存储
SharedPreferences
用于存储少量数据,可存储原始数据:Boolean、Float、Long、Int、String,同时可存储Map、Set、List。通过键值对的形式存储数据,且数据存储在/data/data/<应用程序名>/shared_prefs目录下。
使用步骤:
保存数据
- 通过
Context.getSharedPreferences(“name”,”Context.MODE_...“).edit()
获取SharedPreferences.Editor
对象。 - 通过获取的
editor.put......()
传入数据。 - 最后调用
commit()
或apply()
提交保存数据。
获取数据
- 通过
Context.getSharedPreferences(“name”,”Context.MODE_...“)
获取SharedPreferences
对象。 - 然后调用
get......()
获取数据。
说明commit与apply区别
commit
为同步将数据提交到磁盘,当多个并发提交时会出现等待情况,commit
会返回一个表示是否成功的Boolean
值。apply
为异步将数据提交到磁盘,apply
不会提示说明。- 使用
SharedPreferences
时,如果不关心提交的结果,则推荐使用apply
,效率会更高。
基本使用方法这里不做介绍,主要介绍一下如何存储List
集合、对象。
获取SharedPreferences实例
private SharedPreferences sp;
private static SimpleArrayMap<String, SpUtils> spMap = new SimpleArrayMap<>();
public static SpUtils getInstance(String spName) {
if (TextUtils.isEmpty(spName){
spName = "default_config";
}
if (spUtils == null) {
spUtils = new SPUtils(context, spName);
spMap.put(spName, spUtils);
}
return spUtils;
}
private SPUtils(Context context,String spName) {
sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
}
保存List集合
public static void putList(@NonNull final String key, @NonNullList<T> list, final boolean isCommit) {
Gson gson = new Gson();
String value= gson.toJson(list);
if (isCommit) {
sp.edit().putString(key, value).commit();
} else {
sp.edit().putString(key, value).apply();
}
}
取出List集合
public static List getList(@NonNull final String key, List<T> defaultList) {
List<T> datalist=new ArrayList<T>();
String listJson = spUtils.getString(key, null);
if (null == listJson ) {
return datalist;
}
Gson gson = new Gson();
datalist = gson.fromJson(listJson , new TypeToken<List<T>>() {
}.getType());
return datalist;
}
保存对象
public static void putObject(@NonNull final String key, Object obj,boolean isCommit)throws IOException{
if (obj == null) {
return;
}
//字节流对象
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//对象流
ObjectOutputStream oos = new ObjectOutputStream(baos);
//写入对象流中
oos.writeObject(obj);
//将对象转换成byte数组,并将其进行base64编码
String objString = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT));
//关闭流对象
baos.close();
oos.close();
putString(key, objString,true);
}
取出对象
public static Object getObject(@NonNull final String key,Object defaultObj) throws IOException, ClassNotFoundException{
String wordBase64 = getString(key,"");
if (!TextUtils.isEmpty(wordBase64))
//将base64格式字符串还原成byte数组
byte[] objBytes = Base64.decode(wordBase64.getBytes(), Base64.DEFAULT);
ByteArrayInputStream bais = new ByteArrayInputStream(objBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
//将byte数组转换成product对象
Object obj = ois.readObject();
bais.close();
ois.close();
return obj;
}
return null;
}
2.文件读取与写入
内部存储
数据存储在/data/data/<应用程序名>文件下。
创建私有文件并写入到内部存储:
- 调用
openFileOutput()
并传入文件名称和操作模式。 这将返回一个FileOutputStream
。 write()
写入到文件。close()
关闭流式传输。
从内部存储读取文件:
- 调用
openFileInput()
并向其传递要读取的文件名称。 这将返回一个FileInputStream
。 read()
读取文件字节。close()
关闭流式传输。
操作模式包括:MODE_PRIVATE、MODE_APPEND、MODE_WORLD_READABLE 和 MODE_WORLD_WRITEABLE
Android N 之前使用方法如下:
//写数据
public void writeFile(String fileName,String content){
try{
FileOutputStream fo =openFileOutput(fileName, MODE_PRIVATE);
byte [] bytes = content.getBytes();
fo.write(bytes);
fo.close();
}
catch(Exception e){
e.printStackTrace();
}
}
//读数据
public String readFile(String fileName){
String result="";
try{
FileInputStream fi = openFileInput(fileName);
int length = fi.available();
byte [] buffer = new byte[length];
fi.read(buffer);
result= EncodingUtils.getString(buffer, "UTF-8");
fi.close();
}
catch(Exception e){
e.printStackTrace();
}
return result;
}
Android N 和更高版本的应用如果需要与其他应用共享私有文件,则使用方法如下:
- 置入一个不设防的VmPolicy
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
- 使用FileProvider
- 第一步、在AndroidManifest.xml文件声明。
<manifest>
...
<application>
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="自己应用包名.fileProvider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
...
</application>
</manifest>
- 第二步、在res目录下创建一个xml目录,在该目录下创建file_paths.xml文件并编写如下内容:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="root" path="" />
<files-path name="files" path="" />
<cache-path name="cache" path="" />
<external-path name="external" path="" />
<external-files-path name="external_files" path="" />
<external-cache-path name="external_cache" path="" />
</paths>
在paths节点内部支持以下几个子节点,分别为:
<root-path/>
代表设备的根目录new File("/")
<files-path/>
代表getFilesDir()
<cache-path/>
代表getCacheDir()
<external-path/>
代表Environment.getExternalStorageDirectory()
<external-files-path>
代表getExternalFilesDirs()
<external-cache-path>
代表getExternalCacheDirs()
paths
拥有两个属性分别为name
与path
,path
即为代表目录下的子目录,例:
代表的目录为:getFilesDir() / config。
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="files" path="config" />
</paths>
- 使用方式如下:
Uri uri = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
uri = FileProvider.getUriForFile(context, "自己应用包名.fileProvider", new File("name"));
//对目标应用临时授权该Uri文件
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
//文件转换为Uri对象
uri = Uri.fromFile(new File(filePath));
}
外部文件存储
数据文件位于/mnt/sdcard/文件。
检查SD卡是否可用
public boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
return true;
}
return false;
}
读取SD卡上数据
public String readSDFile(String fileName){
String result="";
try{
FileInputStream fi = new FileInputStream(fileName);
int length = fi.available();
byte [] buffer = new byte[length];
fi.read(buffer);
result = EncodingUtils.getString(buffer, "UTF-8");
fi.close();
} catch(Exception e) {
e.printStackTrace();
}
return res;
}
写入SD卡上数据
public void writeFileSdcardFile(String fileName,String content){
try{
FileOutputStream fo = new FileOutputStream(fileName);
byte [] bytes = content.getBytes();
fo.write(bytes);
fo.close();
} catch(Exception e) {
e.printStackTrace();
}
}
补充
读取assets目录下的文件
try {
InputStream in = Context.getResources().getAssets().open("name");
BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
String result = "";
while((result = br.readLine()) != null){
Log.i(TAG,reslut);
//do something......
}
} catch (IOException e) {
e.printStackTrace();
}
读取raw目录下的文件
try {
InputStream in = Context.getResources().openRawResource(R.raw.name);
BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8"));
String result = "";
while((result = br.readLine()) != null){
Log.i(TAG,reslut);
//do something......
}
} catch (IOException e) {
e.printStackTrace();
}