当前位置:   article > 正文

Android数据存储五种方式总结_在android中有多种存储方式,下面哪种存储是需要配置读写权限的(sharedpreference

在android中有多种存储方式,下面哪种存储是需要配置读写权限的(sharedpreferences

1.Android中的SharedPreferences存储数据方式

SharePreferences是用来存储一些简单配置信息的一种机制,使用Map数据结构来存储数据,以键值对的方式存储,采用了XML格式将数据存储到设备中。例如保存登录用户的用户名和密码。只能在同一个包内使用,不能在不同的包之间使用,其实也就是说只能在创建它的应用中使用,其他应用无法使用。

创建的存储文件保存在/data/data/<package name>/shares_prefs文件夹下。

修改和存储数据
  • 根据Context的getSharedPrerences(key, [模式])方法获取SharedPreference对象;
  • 利用SharedPreference的editor()方法获取Editor对象;
  • 通过Editor的putXXX()方法,将键值对存储数据;
  • 通过Editor的commit()方法将数据提交到SharedPreference内。
demo示例:

  1. package com.example.androidsharedpreferences;
  2. import android.os.Bundle;
  3. import android.util.Log;
  4. import android.view.View;
  5. import android.view.View.OnClickListener;
  6. import android.widget.Button;
  7. import android.widget.EditText;
  8. import android.widget.TextView;
  9. import java.io.BufferedReader;
  10. import java.io.FileInputStream;
  11. import java.io.InputStreamReader;
  12. import android.app.Activity;
  13. import android.content.SharedPreferences;
  14. import android.content.SharedPreferences.Editor;
  15. public class MainActivity extends Activity implements OnClickListener {
  16. private EditText keyET;
  17. private EditText valueET;
  18. private Button insertBtn;
  19. private Button deleteBtn;
  20. private Button modifyBtn;
  21. private Button queryBtn;
  22. private Button clearBtn;
  23. private TextView textView;
  24. public static final String DATABASE = "text";
  25. public static final String PATH = "/data/data/com.example.androidsharedpreferences//shared_prefs/text.xml";
  26. @Override
  27. protected void onCreate(Bundle savedInstanceState) {
  28. super.onCreate(savedInstanceState);
  29. setContentView(R.layout.activity_main);
  30. keyET = (EditText) findViewById(R.id.ed_jian);
  31. valueET = (EditText) findViewById(R.id.ed_zhi);
  32. insertBtn = (Button) findViewById(R.id.button1);
  33. deleteBtn = (Button) findViewById(R.id.button2);
  34. modifyBtn = (Button) findViewById(R.id.button3);
  35. queryBtn = (Button) findViewById(R.id.button4);
  36. clearBtn = (Button) findViewById(R.id.button5);
  37. // 用于显示存储文件中数据
  38. textView = (TextView) findViewById(R.id.tv_jiegou);
  39. insertBtn.setOnClickListener(this);
  40. deleteBtn.setOnClickListener(this);
  41. modifyBtn.setOnClickListener(this);
  42. queryBtn.setOnClickListener(this);
  43. clearBtn.setOnClickListener(this);
  44. }
  45. @Override
  46. public void onClick(View v) {
  47. // 获取SharedPreferences对象
  48. SharedPreferences sp = getSharedPreferences(DATABASE, Activity.MODE_PRIVATE);
  49. // 获取Editor对象
  50. Editor editor = sp.edit();
  51. // 获取界面中的信息
  52. String key = keyET.getText().toString();
  53. String value = valueET.getText().toString();
  54. switch (v.getId()) {
  55. case R.id.button1:
  56. editor.putString(key, value);
  57. editor.commit();
  58. textView.setText(MainActivity.this.print());
  59. break;
  60. case R.id.button2:
  61. editor.remove(key);
  62. editor.commit();
  63. textView.setText(MainActivity.this.print());
  64. break;
  65. case R.id.button3:
  66. editor.putString(key, value);
  67. editor.commit();
  68. textView.setText(MainActivity.this.print());
  69. break;
  70. case R.id.button4:
  71. String result = sp.getString(key, "");
  72. textView.setText("key=" + key + ",value=" + result);
  73. break;
  74. case R.id.button5:
  75. editor.clear();
  76. editor.commit();
  77. textView.setText(MainActivity.this.print());
  78. break;
  79. default:
  80. break;
  81. }
  82. }
  83. /** 获取存储文件的数据 */
  84. private String print() {
  85. StringBuffer buff = new StringBuffer();
  86. BufferedReader reader= null;
  87. try {
  88. reader = new BufferedReader(new InputStreamReader(new FileInputStream(PATH)));
  89. String str;
  90. while ((str = reader.readLine()) != null) {
  91. buff.append(str + "/n");
  92. }
  93. } catch (Exception e) {
  94. e.printStackTrace();
  95. }
  96. Log.d("1111111", buff.toString());
  97. return buff.toString();
  98. }
  99. }

demo下载地址:http://download.csdn.net/detail/qq_31546677/9913230

文章参考地址:http://blog.csdn.net/zuolongsnail/article/details/6556703

2.文件存储

在介绍文件存储之前我们要先了解内存、外部存储、内部存储三个概念,我们先来考虑一个问题:

打开手机设置,选择应用管理,选择任意一个App,然后你会看到两个按钮,一个是清除缓存,另一个是清除数据,那么当我们点击清除缓存的时候清除的是哪里的数据?当我们点击清除数据的时候又是清除的哪里的数据?读完本文相信你会有答案。

在android开发中我们常常听到这样几个概念,内存,内部存储,外部存储,很多人常常将这三个东西搞混,那么我们今天就先来详细说说这三个东西是怎么回事?

内存,我们在英文中称作memory,内部存储,我们称为InternalStorage,外部存储我们称为ExternalStorage,这在英文中本不会产生歧义,但是当我们翻译为中文之后,前两个都简称为内存,于是,混了。

那么究竟什么是内部存储什么是外部存储呢?

首先我们打开DDMS,有一个File Explorer,如下:


这里有三个文件夹需要我们重视,一个是data,一个是mnt,一个是storage,我们下面就详细说说这三个文件夹。

内部存储

data文件夹就是我们常说的内部存储,当我们打开data文件夹之后(没有root的手机不能打开该文件夹),里边有两个文件夹值得我们关注,如下:


一个文件夹是app文件夹,还有一个文件夹就是data文件夹,app文件夹里存放着我们所有安装的app的apk文件,其实,当我们调试一个app的时候,可以看到控制台输出的内容,有一项是uploading .....就是上传我们的apk到这个文件夹,上传成功之后才开始安装。另一个重要的文件夹就是data文件夹了,这个文件夹里边都是一些包名,打开这些包名之后我们会看到这样的一些文件:

1.data/data/包名/shared_prefs
2.data/data/包名/databases
3.data/data/包名/files

4.data/data/包名/cache

如果打开过data文件,应该都知道这些文件夹是干什么用的,我们在使用sharedPreferenced的时候,将数据持久化存储于本地,其实就是存在这个文件中的xml文件里,我们App里边的数据库文件就存储于databases文件夹中,还有我们的普通数据存储在files中,缓存文件存储在cache文件夹中,存储在这里的文件我们都称之为内部存储。

外部存储

外部存储才是我们平时操作最多的,外部存储一般就是我们上面看到的storage文件夹,当然也有可能是mnt文件夹,这个不同厂家有可能不一样。

一般来说,在storage文件夹中有一个sdcard文件夹,这个文件夹中的文件又分为两类,一类是公有目录,还有一类是私有目录,其中的公有目录有九大类,比如DCIM、DOWNLOAD等这种系统为我们创建的文件夹,私有目录就是Android这个文件夹,这个文件夹打开之后里边有一个data文件夹,打开这个data文件夹,里边有许多包名组成的文件夹。

说到这里,我想大家应该已经可以分清楚什么是内部存储什么是外部存储了吧?好,分清楚之后我们就要看看怎么来操作内部存储和外部存储了。

文件的读写常用的是使用:FileOutputStream和FileInputStream下面我们来看demo

  1. package com.example.androidfilestorage;
  2. import android.os.Bundle;
  3. import android.os.Environment;
  4. import android.util.Log;
  5. import android.view.View;
  6. import android.view.View.OnClickListener;
  7. import android.widget.Button;
  8. import android.widget.EditText;
  9. import java.io.ByteArrayOutputStream;
  10. import java.io.File;
  11. import java.io.FileInputStream;
  12. import java.io.FileOutputStream;
  13. import java.io.IOException;
  14. import java.io.OutputStreamWriter;
  15. import android.app.Activity;
  16. import android.content.Context;
  17. public class MainActivity extends Activity implements OnClickListener {
  18. private File json_file, file;
  19. private Button btn_write, btn_read;
  20. private EditText ed_write, ed_read;
  21. private FileOutputStream fos;
  22. FileInputStream inputStream;
  23. @Override
  24. protected void onCreate(Bundle savedInstanceState) {
  25. super.onCreate(savedInstanceState);
  26. setContentView(R.layout.activity_main);
  27. json_file = getFileDir(MainActivity.this, "thumb1");
  28. if (!json_file.exists()) {
  29. json_file.mkdirs();
  30. }
  31. // 建立缓存json数据源文件夹,在没网络的情况下从这里读取数据
  32. file = new File(json_file + "/txt.json");
  33. if (!file.exists()) {
  34. file.getParentFile().mkdirs();
  35. try {
  36. file.createNewFile();
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. Log.d("TestFile", "Create the file:" + file.getPath());
  42. btn_write = (Button) findViewById(R.id.btn_inset);
  43. btn_read = (Button) findViewById(R.id.btn_read);
  44. ed_write = (EditText) findViewById(R.id.ed_inset);
  45. ed_read = (EditText) findViewById(R.id.ed_read);
  46. btn_write.setOnClickListener(this);
  47. btn_read.setOnClickListener(this);
  48. }
  49. /**
  50. * 判断内部存储还是外部存储,带SD卡使用外部存储,不带SD卡使用内部存储。
  51. */
  52. public File getFileDir(Context context, String uniqueName) {
  53. String cachePath;
  54. if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
  55. || !Environment.isExternalStorageRemovable()) {
  56. cachePath = context.getExternalFilesDir(uniqueName).getPath();
  57. } else {
  58. cachePath = context.getFilesDir().getPath();
  59. }
  60. return new File(cachePath);
  61. }
  62. @Override
  63. public void onClick(View v) {
  64. String text = ed_write.getText().toString();
  65. switch (v.getId()) {
  66. case R.id.btn_inset:
  67. try {
  68. fos = new FileOutputStream(file);
  69. OutputStreamWriter osw = new OutputStreamWriter(fos);
  70. osw.write(text);
  71. osw.flush();
  72. osw.close();
  73. fos.close();
  74. } catch (IOException e) {
  75. e.printStackTrace();
  76. }
  77. break;
  78. case R.id.btn_read:
  79. try {
  80. inputStream = new FileInputStream(file);
  81. byte[] bytes = new byte[1024];
  82. ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
  83. while (inputStream.read(bytes) != -1) {
  84. arrayOutputStream.write(bytes, 0, bytes.length);
  85. }
  86. inputStream.close();
  87. arrayOutputStream.close();
  88. String content = new String(arrayOutputStream.toByteArray());
  89. ed_read.setText(content);
  90. } catch (Exception e) {
  91. }
  92. break;
  93. default:
  94. break;
  95. }
  96. }
  97. }

文件的读写需要的权限:
  1. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  2. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
  3. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
demo下载地址: http://download.csdn.net/detail/qq_31546677/9913232

文章参考地址:

内部存储和外部存储理解:http://www.cnblogs.com/jingmo0319/p/5586559.html

3.sqlite数据库存储

sqlite以前介绍过了在这里就不介绍了需要的参考我的博客:http://blog.csdn.net/qq_31546677/article/details/68486012

4.ContentProvider存储

适用范围

对于什么情况下才会用到自定义的ContentProvider,官方文档的Dev Guide是这样描述的:

如果你想要提供以下的一种或几种特性的时候你才需要构造一个ContentProvider:

  • 你想要为其它的应用提供复杂的数据或者文件;
  • 你想允许用户从你的应用中拷贝复杂的数据到其它的应用中;
  • 你想要使用搜索框架来提供自定义的搜索策略。

你完全不需要ContentProvider来调用一个SQLite数据库,如果这种调用完全在你自己的应用之中。

 

也就是说,ContentProvider的作用是为别的应用调用本应用中的数据或者文件提供接口,而它也是唯一的跨应用数据传递的接口。如果仅仅是同一个应用中的数据传递,则完全没有必要使用到自定义的ContentProvider。

另一方面,虽然ContentProvider也能组织文件数据或者SharedPreferences(其实也是文件数据)这种数据,但大多数情况下ContentProvider是作为SQLite数据库的调用接口来被继承的。其原因大概是在于重写的query()方法始终需要返回Cursor,而Cursor作为数据库数据的容器,并没有提供直接往Cursor中写入数据的方法。

大体实现步骤

1.      创建一个数据源,例如继承SQLiteOpenHelper创建一个SQLite数据库;

2.      创建一个继承自ContentProvider的类,并重写insert、delete、query、update、getType、onCreate方法,在这些方法中实现对数据源的操作;

3.      在AndroidManifest.xml文件中添加<provider>标签,两个必写的属性是android:name和android:authorities;

4.      在本应用或者其它应用的Activity、Service等组件中使用ContentResolver通过对应的URI来操作该自定义ContentProvider。

名词解释

URL

Android各种类型的URI基本上都是有固定格式的,对于ContentProvider而言,一般形如

content://com.test.cp.MyProvider/phone/1

的URI,其中:

content://是固定字段,必需;

com.test.cp.MyProvider表示authority,是AndroidManifest.xml文件中<provider>标签的android:authorities属性值,或者是远程数据源的主机名,必需;

phone/1表示path,是数据源路径,非必需,其中的phone对于数据库来说可以视为表名,1表示的是该条数据的编号,如果没有则一般认为是返回当前路径(当前表)中的所有数据。

另外还可以根据自己的需要来进一步定义后续的字段。

UriMatch对象

1.        通过new  UriMatcher(UriMatcher.NO_MATCH); 实例化,常量NO_MATCH作为参数表示不匹配任何URI;

2.        实例化后调用addURI方法注册URI,该方法有三个参数,分别需要传入URI字符串的authority部分、path部分以及自定义的整数code三者;

3.        在其它地方调用match方法匹配相应的URI,需要传入Uri作为唯一的参数,返回上述自定义的code值。

至于其初始化的位置,如前所述,网上绝大多数示例都将其放入静态域中实例化,原因不明。实际上放到onCreate方法中也没什么问题。

getType方法

ContentProvider必须重写的6个方法中,除了初始化方法onCreate以及数据操作的4个方法以外,还有一个getType方法。它的作用是根据URI返回该URI所对应的数据的MIME类型字符串。这种字符串的格式分为两段:“A/B”。其中A段是固定的,集合类型(如多条数据)必须是vnd.android.cursor.dir,非集合类型(如单条数据)必须是vnd.android.cursor.item;B段可以是自定义的任意字符串;A、B两段通过“/”隔开。这个MIME类型字符串的作用是要匹配AndroidManifest.xml文件<activity>标签下<intent-filter>标签的子标签<data>的属性android:mimeType。如果不一致,则会导致对应的Activity无法启动。

demo示例主要代码

  1. package com.example.androidcustomcontentprovider;
  2. import android.os.Bundle;
  3. import android.os.Handler;
  4. import android.os.Message;
  5. import android.util.Log;
  6. import android.view.View;
  7. import android.view.View.OnClickListener;
  8. import android.widget.AdapterView;
  9. import android.widget.AdapterView.OnItemClickListener;
  10. import android.widget.Button;
  11. import android.widget.EditText;
  12. import android.widget.ListView;
  13. import android.widget.SimpleAdapter;
  14. import android.widget.Toast;
  15. import java.util.ArrayList;
  16. import java.util.HashMap;
  17. import java.util.List;
  18. import java.util.Map;
  19. import android.app.Activity;
  20. import android.content.ContentResolver;
  21. import android.content.ContentValues;
  22. import android.database.Cursor;
  23. import android.net.Uri;
  24. public class MainActivity extends Activity implements OnClickListener {
  25. private Button btnadd, btnqueryall, btndel, btnupdate;
  26. private EditText edtname, edtage;
  27. private ListView lvall;
  28. private int id;
  29. private Uri url;
  30. private String path="content://com.example.androidcustomcontentprovider.myprovider/person";
  31. private List<Person> persons;
  32. private SimpleAdapter simpleAdapter;
  33. private Handler handler = new Handler() {
  34. @Override
  35. public void handleMessage(Message msg) {
  36. List<Map<String, Object>> data = (List<Map<String, Object>>) msg.obj;
  37. Log.d("data", "---" + data.size());
  38. simpleAdapter = new SimpleAdapter(MainActivity.this, data, R.layout.list_item,
  39. new String[] { "id", "name", "age" }, new int[] { R.id.tvId, R.id.tvname, R.id.tvage });
  40. lvall.setAdapter(simpleAdapter);
  41. simpleAdapter.notifyDataSetChanged();
  42. }
  43. };
  44. @Override
  45. protected void onCreate(Bundle savedInstanceState) {
  46. super.onCreate(savedInstanceState);
  47. setContentView(R.layout.activity_main);
  48. persons = new ArrayList<Person>();
  49. btnqueryall = (Button) this.findViewById(R.id.btnqueryall);
  50. btnadd = (Button) this.findViewById(R.id.btnadd);
  51. edtname = (EditText) this.findViewById(R.id.edtname);
  52. edtage = (EditText) this.findViewById(R.id.edtage);
  53. btndel = (Button) this.findViewById(R.id.btndel);
  54. btnupdate = (Button) this.findViewById(R.id.btnupdate);
  55. lvall = (ListView) this.findViewById(R.id.lvall);
  56. btnadd.setOnClickListener(this);
  57. btnqueryall.setOnClickListener(this);
  58. btndel.setOnClickListener(this);
  59. btnupdate.setOnClickListener(this);
  60. lvall.setOnItemClickListener(new OnItemClickListener() {
  61. @Override
  62. public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
  63. Log.d("position:", "" + position);
  64. Person person = persons.get(position);
  65. Log.d("data_onitemClick",
  66. "id:" + person.getId() + "name:" + person.getName() + "age:" + person.getAge());
  67. edtname.setText(person.getName());
  68. edtage.setText("" + person.getAge());
  69. }
  70. });
  71. }
  72. @Override
  73. public void onClick(View v) {
  74. switch (v.getId()) {
  75. case R.id.btnadd:
  76. ContentResolver contentResolver = MainActivity.this.getContentResolver();
  77. url = Uri.parse(path);
  78. ContentValues values = new ContentValues();
  79. values.put("name", edtname.getText().toString());
  80. values.put("age", edtage.getText().toString());
  81. Uri result = contentResolver.insert(url, values);
  82. Log.d("result", result.toString());
  83. if (edtname.getText().toString().equals("") || edtage.getText().toString().equals("")) {
  84. Toast.makeText(MainActivity.this, "输入内容为空", Toast.LENGTH_LONG).show();
  85. } else {
  86. Toast.makeText(MainActivity.this, "添加成功", Toast.LENGTH_LONG).show();
  87. getAllDate();
  88. }
  89. break;
  90. case R.id.btndel:
  91. ContentResolver contentResolver1 = MainActivity.this.getContentResolver();
  92. url = Uri.parse(path);
  93. Cursor cursor2 = MainActivity.this.getContentResolver().query(url, null, null, null, null);
  94. while(cursor2.moveToNext()){
  95. id=cursor2.getInt(cursor2.getColumnIndex("_id"));
  96. }
  97. Log.d("result_delete", "" + id);
  98. // 构建Uri
  99. String url1 = "content://com.example.androidcustomcontentprovider.myprovider/person/"
  100. + id;
  101. Uri uri = Uri.parse(url1);
  102. int result1 = contentResolver1.delete(uri, null, null);
  103. Log.d("result_delete", "" + result1);
  104. getAllDate();
  105. break;
  106. case R.id.btnupdate:
  107. ContentResolver contentResolver11 = MainActivity.this.getContentResolver();
  108. url = Uri.parse(path);
  109. Cursor cursor21 = MainActivity.this.getContentResolver().query(url, null, null, null, null);
  110. while(cursor21.moveToNext()){
  111. id=cursor21.getInt(cursor21.getColumnIndex("_id"));
  112. }
  113. Log.d("result_delete", "" + id);
  114. // 构建Uri
  115. String url12 = "content://com.example.androidcustomcontentprovider.myprovider/person/"
  116. + id;
  117. Uri uri1 = Uri.parse(url12);
  118. ContentValues values1 = new ContentValues();
  119. values1.put("name", edtname.getText().toString());
  120. values1.put("age",
  121. Integer.parseInt(edtage.getText().toString()));
  122. int result12 = contentResolver11.update(uri1, values1, null, null);
  123. Log.d("update result:" ,""+ result12);
  124. System.out.println("update result:" + result12);
  125. getAllDate();
  126. break;
  127. case R.id.btnqueryall:
  128. getAllDate();
  129. break;
  130. default:
  131. break;
  132. }
  133. }
  134. public void getAllDate() {
  135. persons.clear();
  136. lvall.setAdapter(null);
  137. url = Uri.parse(path);
  138. Cursor cursor = MainActivity.this.getContentResolver().query(url, new String[] { "_id", "name", "age" }, null,
  139. null, "_id");
  140. while (cursor.moveToNext()) {
  141. Person person = new Person();
  142. person.setId(cursor.getInt(cursor.getColumnIndex("_id")));
  143. person.setName(cursor.getString(cursor.getColumnIndex("name")));
  144. person.setAge(cursor.getInt(cursor.getColumnIndex("age")));
  145. persons.add(person);
  146. }
  147. cursor.close();
  148. List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
  149. Map<String, Object> map = null;
  150. for (int i = 0; i < persons.size(); i++) {
  151. map = new HashMap<String, Object>();
  152. map.put("id", persons.get(i).getId());
  153. map.put("name", persons.get(i).getName());
  154. map.put("age", persons.get(i).getAge());
  155. data.add(map);
  156. }
  157. if (data.size() >= persons.size()) {
  158. }
  159. Message msg = handler.obtainMessage();
  160. msg.obj = data;
  161. handler.sendMessage(msg);
  162. }
  163. }
demo下载地址: http://download.csdn.net/detail/qq_31546677/9913234

文章参考地址:http://www.cnblogs.com/wangfeng520/p/5099465.html

http://blog.csdn.net/zuolongsnail/article/details/6566317

http://blog.csdn.net/worker90/article/details/7016430

http://blog.csdn.net/amazing7/article/details/51324022

5.网络存储

网络操作博主已经讲过了,可以参考博主的这一篇文章基本没问题:http://blog.csdn.net/qq_31546677/article/details/58603185

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/576329
推荐阅读
相关标签
  

闽ICP备14008679号