Android文件数据存储

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33706840/article/details/81450556

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拥有两个属性分别为namepathpath即为代表目录下的子目录,例:
    代表的目录为: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();
    }

后续为大家将会为大家奉上关于Java流对象的各种方式读取操作…

猜你喜欢

转载自blog.csdn.net/qq_33706840/article/details/81450556