Android系统有五种数据存储形式,分别是文件存储、SP存储、数据库存储、contentprovider 内容提供者、网络存储。其中,前四个是本地存储。存储的类型包括简单文本、窗口状态存储、音频视频数据、XML注册文件的各种数据。各种存储形式的特点不尽相同,因此对于不同的数据类型有着固定的存储形式,本文为演示方便给出的案例基本相同,都是是采用账号登录来演示数据存储,保存账号和密码信息,下次登录时记住账号和密码。重在说明各种存储形式的原理。

文件存储:

以I/O流的形式把数据存入手机内存或SD卡,可以存储大数据,如音乐、图片或视频等。对于手机内存来说系统会根据每个应用的包名创建一个/data/data/包名/的文件夹,访问自己包名下的目录是不需要权限的,并且 Android 已经提供了非常简便的 API 可以直接去访问该文件夹。访问时可以用getFilesDir()和getCacheDir(),两个的区别是系统会自动清理后者中的内容。

SD卡中的文件通常位于mnt/sdcard目录下,不同生产商生产的手机这个路径可能不同。操作sd卡的时通常要判断下sd卡是否可用以及剩余空间是否足够,因为部分手机的SD卡可卸载,SD卡处于非挂载状态时,无法进行读写操作。另外一点,对SD卡的读取和写入操作均需要相应的权限,否则无法完成。获取SD卡路径的方法是Environment.getExternalStorageDirectory(),其余操作与文件存储基本类似。

文件存储位置:

SD卡存储路径:

数据存储在手机内存的实现方法:

package com.example.qqload;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader; import com.example.qqload_sp.R; import android.os.Bundle;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.text.TextUtils;
import android.view.Menu;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast; public class MainActivity extends Activity {
private EditText et_qq;
private EditText et_password;
private CheckBox cb_remenber; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_qq = (EditText) findViewById(R.id.et_qq);
et_password = (EditText) findViewById(R.id.et_password);
cb_remenber = (CheckBox) findViewById(R.id.cb_remenber);
File file = new File(getFilesDir(), "info.txt");
// File file = new File(getCacheDir(), "info.txt"); 缓存中存放数据
if (file.exists() && file.length() > 0) {
try {
FileInputStream fis = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(
fis));
String line = br.readLine();
String qq = line.split("##")[0];
String password = line.split("##")[1];
et_qq.setText(qq);
et_password.setText(password);
fis.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} public void login(View view) {
String qq = et_qq.getText().toString().trim();
String password = et_password.getText().toString().trim();
if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(password)) {
Toast.makeText(this, "密码或者用户名不能为空", 0).show();
return;
}
if (cb_remenber.isChecked()) {
File file = new File(getFilesDir(), "info.txt");
try {
FileOutputStream fos = new FileOutputStream(file);
fos.write((qq + "##" + password).getBytes());
fos.close();
Toast.makeText(MainActivity.this, "保存成功", 0).show();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "保存失败", 0).show();
e.printStackTrace();
}
}
}
}

数据存储在SD卡中的实现方法:

package com.example.qqload;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.text.Format; import com.example.qqload_sp.R; import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.view.Menu;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast; public class MainActivity extends Activity {
private EditText et_qq;
private EditText et_password;
private CheckBox cb_remenber; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_qq = (EditText) findViewById(R.id.et_qq);
et_password = (EditText) findViewById(R.id.et_password);
cb_remenber = (CheckBox) findViewById(R.id.cb_remenber);
File file = new File(Environment.getExternalStorageDirectory(), "info.txt");
if (file.exists() && file.length() > 0) {
try {
FileInputStream fis = new FileInputStream(file);
BufferedReader br = new BufferedReader(new InputStreamReader(
fis));
String line = br.readLine();
String qq = line.split("##")[0];
String password = line.split("##")[1];
et_qq.setText(qq);
et_password.setText(password);
fis.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} public void login(View view) {
String qq = et_qq.getText().toString().trim();
String password = et_password.getText().toString().trim();
if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(password)) {
Toast.makeText(this, "密码或者用户名不能为空", 0).show();
return;
}
if (cb_remenber.isChecked()) {
File file = new File(Environment.getExternalStorageDirectory(), "info.txt");
//判断SD卡是否挂载
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
Toast.makeText(MainActivity.this, "SD卡不可用", 0).show();
return;
}
//判断SD卡大小是否充足
long size = Environment.getExternalStorageDirectory().getFreeSpace();
String info = Formatter.formatFileSize(this, size);
//此处存储数据较小就不进行判断
Toast.makeText(this, "可用空间" + info, 0).show(); try {
FileOutputStream fos = new FileOutputStream(file);
fos.write((qq + "##" + password).getBytes());
fos.close();
Toast.makeText(MainActivity.this, "保存成功", 0).show();
} catch (Exception e) {
Toast.makeText(MainActivity.this, "保存失败", 0).show();
e.printStackTrace();
}
}
}
}

SP存储:

SP存储本质上是一个XML文件,以键值对的形式存入手机内存中。常用于存储简单的参数设置,如登陆账号密码的存储,窗口功能状态的存储等,该存储文件位于:data/data/包名/shared_prefs文件夹中。使用的时候,首先需要通过context.getSharedPrefrences(String name,int mode)获取SharedPrefrences的实例对象,存储数据时,用SharedPrefrences的实例对象得到SharedPrefrences文件的编辑器,在编辑器中用putXxx()添加数据,之后务必用commit提交数据,否则无法获取数据。取数据时,直接用getXxx()方法。

sp存储自动生成xml文件,其的路径如下:

sp存储的实现方法:

package com.example.qqload;
import com.example.qqload_sp.R; import android.os.Bundle;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.text.TextUtils;
import android.view.Menu;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText et_qq;
private EditText et_password;
private CheckBox cb_remenber;
private SharedPreferences sp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_qq = (EditText) findViewById(R.id.et_qq);
et_password = (EditText) findViewById(R.id.et_password);
cb_remenber = (CheckBox) findViewById(R.id.cb_remenber);
sp = this.getSharedPreferences("config", 0);
String qq = sp.getString("qq","");
String password = sp.getString("password","");
et_qq.setText(qq);
et_password.setText(password);
}
public void login(View view){
String qq = et_qq.getText().toString().trim();
String password = et_password.getText().toString().trim();
if(TextUtils.isEmpty(qq)||TextUtils.isEmpty(password)){
Toast.makeText(this,"密码或者用户名不能为空",0).show();
return;
}
if(cb_remenber.isChecked()){
Editor edit = sp.edit();
edit.putString("qq",qq);
edit.putString("password",password);
edit.commit();
}
}
}

数据库存储:

数据库所有信息都存储在单一文件内,占用内存小,并且支持基本SQL语法,是项目中经常被采用的一种数据存储方式,通常用于存储用户信息等,例如在手机上做一个学生信息管理系统。SQLite 是一款内置到移动设备上的轻量型的数据库,SQLiteOpenHelper 是Android 提供的一个抽象工具类,负责管理数据库的创建、升级工作。数据库的路径为:/data/data/应用包名/databases/数据库。如果想创建数据库,就需要自定义一个类继承SQLiteOpenHelper,然后覆写其中的抽象方法,指定数据库名、版本号。在onCreate() 方法中通过执行sql 语句实现表的创建。如果只是创建出来该类并不会真正的去创建数据库,而是需要通过执行helper.getWritableDatabase()或者hepler.getReadableDatabase()。另外想要对创建的数据库进行增删改查的操作可以单独定义一个类实现。增删改查操作有两种方式,一是直接执行sql语句,另一个是Android自身的API实现。用数据库实现账号登录显得有些大材小用,为演示数据库的原理本文给出的案例是用数据库记录多个用户的账号和密码信息,并把最后一个账号信息回显在界面。但实际应用中很少这样做。

从手机文件中导出数据库文件并不可以直接打开,因此可以用可视化工具和sqlite3操作工具进行查看。这里介绍sqlite3工具的使用。具体需要的步骤如下:

1. 执行adb shell命令进入Linuxne内核;

2. 使用cd进入数据库所在的路径 cd: /data/data/应用包名/databases;

3. 进入数据库模式: sqlite3 数据库名.db;

4. 执行SQL语句

Sqlite3操作演示:

数据库存储路径:

数据库实现方法,先创建一个类继承SqliteOpenHelper,在类中创建数据库和表:

package com.example.qqload.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper; public class UserDBOpenhelper extends SQLiteOpenHelper {
public UserDBOpenhelper(Context context) {
super(context, "user.db", null, 1);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase arg0) {
arg0.execSQL("create table user (_id integer primary key autoincrement,name vachar(20),password varchar(20))");
}
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
}
}

创建一个工具类实现对数据库的操作:

package com.example.qqload.db.dao;

import java.util.ArrayList;
import java.util.List; import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import com.example.qqload.db.UserDBOpenhelper; public class UserDao {
private UserDBOpenhelper helper;
public UserDao(Context context){
helper = new UserDBOpenhelper(context);
}
public long add(String name,String password){
SQLiteDatabase db = helper.getWritableDatabase();
//用SQL语句实现增加数据的功能
//db.execSQL("insert into user (name,passeord) values (?,?)", new Object[]{name,password});
//android自身API实现修改功能可以有返回值
ContentValues values =new ContentValues();
values.put("name", name);
values.put("password", password);
long result = db.insert("user", null, values); //带返回值,表示添加在哪一行
db.close();
return result;
}
public List<user> findAll(){
List<user> list =new ArrayList<user>();
SQLiteDatabase db = helper.getReadableDatabase();
//Cursor cursor = db.rawQuery("select name, password from user", null);
Cursor cursor = db.query("user", new String[]{"name","password"}, null, null, null, null, null);
while(cursor.moveToNext()){
String name = cursor.getString(0);
String password = cursor.getString(1);
user us = new user();
us.setName(name);
us.setPassword(password);
list.add(us);
}
cursor.close();
db.close();
return list;
}
}

在主方法中实现账号登录和记录

package com.example.qqload;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.List; import com.example.qqload.db.dao.UserDao;
import com.example.qqload.db.dao.user;
import com.example.qqload.R; import android.os.Bundle;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.text.TextUtils;
import android.view.Menu;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast; public class MainActivity extends Activity {
private EditText et_qq;
private EditText et_password;
private CheckBox cb_remenber;
private UserDao dao;
private List<user> list; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_qq = (EditText) findViewById(R.id.et_qq);
et_password = (EditText) findViewById(R.id.et_password);
cb_remenber = (CheckBox) findViewById(R.id.cb_remenber);
user u = new user();
dao = new UserDao(MainActivity.this);
list = dao.findAll();
if (list.size() == 0) {
et_qq.setText("");
et_password.setText("");
} else {
System.out.println("大小:" + list.size());
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i).getName() + "::::" + list.get(i).getPassword());
}
u = list.get(list.size()-1);
String qq = u.getName();
String password = u.getPassword();
et_qq.setText(qq);
et_password.setText(password);
}
} public void login(View view) {
String qq = et_qq.getText().toString().trim();
String password = et_password.getText().toString().trim();
if (TextUtils.isEmpty(qq) || TextUtils.isEmpty(password)) {
Toast.makeText(this, "密码或者用户名不能为空", 0).show();
return;
}
if (cb_remenber.isChecked()) {
dao.add(qq, password); //在工具类添加增加功能
Toast.makeText(MainActivity.this, "保存成功", 0).show();
}
}
}

用数据库实现账号登录案例的目录结构如下所示:

Android系统的五种数据存储形式(一)的更多相关文章

  1. Android系统的五种数据存储形式(二)

    之前介绍了Android系统下三种数据存储形式,今天补充介绍另外两种,分别是内容提供者和网络存储.有些人可能认为内存提供者和网络存储更偏向于对数据的操作而不是数据的存储,但这两种方式确实与数据有关,所 ...

  2. Android五种数据存储方式

    android 五种数据存储 :SharePreferences.SQLite.Contert Provider.File.网络存储 Android系统提供了四种存储数据方式.分别为:SharePre ...

  3. Android中的5种数据存储方式

    本文转自  http://hi.baidu.com/maguowei/blog/item/7aca46c25574a33ae5dd3ba4.htmlAndroid数据存储Android提供了5种方式存 ...

  4. Android中常用的五种数据存储方式

    第一种: 使用SharedPreferences存储数据 适用范围: 保存少量的数据,且这些数据的格式非常简单:字符串型.基本类型的值.比如应用程序的各种配置信息(如是否打开音效.是否使用震动效果.小 ...

  5. [ Android 五种数据存储方式之四 ] —— ContentProvider存储数据

    Android这个系统和其他的操作系统还不太一样,我们需要记住的是,数据在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据.那这个时候有读者就会提出问题,难道两个 ...

  6. [ Android 五种数据存储方式之三 ] —— SQLite存储数据

    SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能.此外它还是开源的,任何人都可以使用它.许多开源项目((Mozilla, PHP, Python)都使用了 ...

  7. [ Android 五种数据存储方式之二 ] —— 文件存储数据

    关于文件存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的. 文件可用来存放大量数据,如文本.图片.音 ...

  8. [ Android 五种数据存储方式之一 ] —— SharedPreferences存储数据

    SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数. 主要是保存一些常用的配置比如窗口状态,一般在Activity中 重载窗口状态onSaveInstanceS ...

  9. Android编程中的5种数据存储方式

    Android编程中的5种数据存储方式 作者:牛奶.不加糖 字体:[增加 减小] 类型:转载 时间:2015-12-03我要评论 这篇文章主要介绍了Android编程中的5种数据存储方式,结合实例形式 ...

随机推荐

  1. Android探索之BroadcastReceiver具体使用以及安全性探究

    前言: 最近的计划是学习一下iOS的NSNotificationCenter,突然想起来的Android的广播机制,所以还是觉得先对BroadcastReceiver来个全面的总结然后再去学习NSNo ...

  2. Restore Volume 操作 - 每天5分钟玩转 OpenStack(60)

    前面我们 backup 了 voluem,今天我们将讨论如何 restore volume. restore 的过程其实很简单,两步走: 在存储节点上创建一个空白 volume. 将 backup 的 ...

  3. Util应用程序框架公共操作类(八):Lambda表达式公共操作类(二)

    前面介绍了查询的基础扩展,下面准备给大家介绍一些有用的查询封装手法,比如对日期范围查询,数值范围查询的封装等,为了支持这些功能,需要增强公共操作类. Lambda表达式公共操作类,我在前面已经简单介绍 ...

  4. vmware网卡设置详解

    转载请注明出处!本文连接及作者.不得用于商业用途! http://hi.baidu.com/quantumcloud/blog/item/9156a6c584996c179c163d5b.html B ...

  5. 修正IE6不支持position:fixed的bug(转)

    众所周知IE6不支持position:fixed,这个bug与IE6的双倍margin和不支持PNG透明等bug一样臭名昭著.前些天我做自己的博客模板的时候,遇到了这个问题.当时就简单的无视了IE6— ...

  6. Myeclipse中导入项目后java类中汉字注释出现乱码问题(已解决)

    今天重装系统,安装了新的Myeclipse后,导入之前的项目后,,出现了乱码问题.乱码问题主要是java类中的注释,而jsp页面中汉字却完好如初: 右键项目,查看项目的编码格式,UTF-8,把java ...

  7. 浅析JS中的模块规范(CommonJS,AMD,CMD)

    如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. 现在就看看吧,这些规范到底是啥东西,干嘛的. 一.CommonJS ...

  8. 【JUC】JUC线程池框架综述

    一.前言 在分析完了JUC的锁和集合框架后,下面进入JUC线程池框架的分析,下面给出JUC线程池的总体框架,之后再逐一进行分析. 二.JUC线程池框架图 说明:从上图可知,JUC线程池框架中的其他接口 ...

  9. uploadify上传错误:uncaught exception: call to startUpload failed原因

    这个不是什么tab的问题,而是可能有多个上传的div或者input(含有相同的name或者ID)导致的 如果有两个不同的上传按钮,那么他们的name,id要设置得不一样. <div id='to ...

  10. TCP的阻塞和重传机制

    TCP的阻塞和重传机制 网络拥堵 现在网络上大部分的网络请求都是以TCP的方式进行传输的了.网络链路是固定的,各种链路情况也是不一样的.网络拥堵一直是TCP协议设计和使用的时候尽力要避免的.比如,从T ...