概述
数据持久化存储
主要有以下三种方式进行数据持久化存储
一.文件存储
存储文件
最基本的存储方式,会把存储内容原封不动保存到文件中,主要存储二进制数据和简单的文本数据。如果想存储复杂的数据,就要有自己的格式规范
在布局文件中添加一个EditText来输入东西
实现过程就是:在onCreate()方法中创建一个EditText的实例,然后再重写onDestory()方法,这样确保在活动销毁前一定会调用这个实例,在onDestroy()方法中,定义一个string类来获取输入的内容,然后调用save()方法来完成存储文件功能。save()中,首先通过openFileOutput()方法得到一个FileOutputStream对象,然后再借助它构成一个OutputStreamWriter对象,接着再使用OutputStreamWriter构建出一个BufferedWriter对象,这样就可以通过BufferedWriter写入文本了。
openFileOutput()方法,是Context类提供的,接受两个参数,第一个参数是文件名,不用包含路径,第二个参数是操作模式,主要有两种模式,MODE_PRIVATE是默认操作模式,同文件名,覆盖原内容,MODE_APPEND同文件名,追加内容,不存在就新创建文件。
mainActivity中代码如下:
public class MainActivity extends AppCompatActivity {
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText=(EditText)findViewById(R.id.editText);
}
@Override
protected void onDestroy(){
super.onDestroy();
String inputText=editText.getText().toString();
save(inputText);
}
public void save(String inputText){
FileOutputStream out=null;
BufferedWriter writer=null;
try{
out=openFileOutput("date", Context.MODE_PRIVATE);
writer=new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
}catch (IOException e){
e.printStackTrace();
}finally {
try{
if(writer!=null) {
writer.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
}
寻找数据在边框上的Device File Explorer,点击data->data->自己 文件的包名->files
![1534167974289.png](https://i.loli.net/2018/08/13/5b718bc0da5d4.png)
读取文件
类似于存储,Context类还提供一个openFileInput()方法,用于从文件中读取数据,这个方法要比openFileOutput简单,他只接受一个参数,就是文件名,然后到默认路径加载文件,并返回一个FileInputStream对象,再使用相应java流就可将数据读取出来。
通过openFileInput()方法得到一个FileInputStream对象,然后借助它构建一个InputStreamReader对象,然后通过BufferedReader进行读取,读出的内容存放在StringBuilder对象中,再返回
TextUtils.isEmpty()方法可以一次性判断两种情况下的空,null和空字符串
setSelection()方法将光标移动到末尾以便继续输入
public class MainActivity extends AppCompatActivity {
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText=(EditText)findViewById(R.id.editText);
String inputText=load();
if(!TextUtils.isEmpty(inputText)){
editText.setText(inputText);
editText.setSelection(inputText.length());
Toast.makeText(this,"Restoring succeeded",Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onDestroy(){
super.onDestroy();
String inputText=editText.getText().toString();
System.out.print(inputText);
save(inputText);
}
public void save(String inputText){
FileOutputStream out=null;
BufferedWriter writer=null;
try{
out=openFileOutput("date", Context.MODE_PRIVATE);
writer=new BufferedWriter(new OutputStreamWriter(out));
writer.write(inputText);
}catch (IOException e){
e.printStackTrace();
}finally {
try{
if(writer!=null) {
writer.close();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
public String load(){
FileInputStream in=null;
BufferedReader reader=null;
StringBuilder context=new StringBuilder();
try{
in=openFileInput("date");
reader=new BufferedReader(new InputStreamReader(in));
String line="";
while ((line=reader.readLine())!=null){
context.append(line);
}
}catch (IOException e)
{
e.printStackTrace();
}finally {
if(reader!=null)
{
try{
reader.close();
}catch (IOException e)
{
e.printStackTrace();
}
}
}
return
context.toString();
}
}
这样就把date文件中的内填充到了EditText中。
二.SharedPreferences存储
存储多种数据类型,以键值对方式存储,取出要取出相应的键,就能取出对应的值
存储
想用SharedPreference存储数据,要首先获取到SharedPreferences对象,有三种获取方式
1.Context类中的getSharedPreferences()方法
此方法接受两个参数,第一个参数是文件名,第二个参数是模式,现在只有一种模式,就是MODE_PRIVATE,表示文件中数据只有当前程序才可以对文件进行读取,与直接传入0效果相同,之前的模式全部舍弃了
2.Activity中的getPreferences()方法
只接受一个参数,因为使用这个方法会把当前活动的类名作为SharedPreferences文件名
3.PreferenceManager的getDefaultSharedPreferences()方法
静态方法,只接受一个Context参数,并将当前活动的包名作为前缀来命名SharedPreference文件名
获得对象后,就可以向SharedPreferences文件中存储数据了,三步实现
(1)调用SharedPreferences的edit()方法获取一个SharedPreferences.Editor对象
(2)向SharedPreferences.Editor对象中添加数据,布尔型就用putBoolean方法,类似有putInt( ,)
(3)调用apply()方法将数据提交,从而完成存储。
public class MainActivity extends AppCompatActivity {
private Button saveData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
saveData=(Button)findViewById(R.id.saveData);
saveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences.Editor editor=getSharedPreferences("data",MODE_PRIVATE).edit();
editor.putString("name","haha");
editor.putBoolean("married",false);
editor.putInt("age",28);
editor.apply();
}
});
}
}
存储结果如下:
![1534671248104.png](https://i.loli.net/2018/08/19/5b7939c15155b.png)
读取
同样用按钮点击事件来实现,通过打印日志看效果。
public class MainActivity extends AppCompatActivity {
private Button saveData;
private Button restore;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
saveData = (Button) findViewById(R.id.saveData);
saveData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
editor.putString("name", "Tom");
editor.putBoolean("married", false);
editor.putInt("age", 28);
editor.apply();
}
});
restore = (Button) findViewById(R.id.restore);
restore.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
String name = pref.getString("name", "");
boolean married = pref.getBoolean("married", false);
int age = pref.getInt("age", 0);
Log.d("MainActivity",
"name"+name);
Log.d("MainActivity",
"age is"+age);
Log.d("MainActivity",
"married"+married);
}
});
}
}
通过getSharedPreferfences()方法获得SharedPreferences的对象,通过getString()方法返回对应值,此方法有两个值,第一个是那个键,第二个是默认返回值。
这里我不知道发生了啥,刚开始一直调不通,后来给电脑插电就好了。还有Boolean替代boolean,打印出来的值是分开的而不是一起的。
三.数据库存储
安卓内置一个关系数据库SQLite,存储大型复杂的关系数据库
创建数据库
SQLiteOpenHelper是一个抽象类,可以方便数据库的管理,在运用时要重写他的两个抽象方法onCreate()和onUpgrade(),需要在帮助类里进行重写,从而实现创建升级数据库。还有两个实例方法getReadableDatabase()和getWriteableDatabase(),都可以创建或者打开一个数据库,(已经存在就打开,否则创建),返回一个可供读写的对象,不同的是当数据库不可写入时,getReadableDatabase()将以只读方式打开,而getWriteableDatabase()抛出异常。
构造方法有两种,一般选择参数少的那个,只有四个参数,第一个参数Context,第二个参数数据库名,第三个参数是查询数据库返回自定义的Cursor一般为null,第四个参数是当前数据库的版本号,可用于对数据库进行升级操作。
首先新建一个MyDatabaseHelper类,让他继承自SQLiteOpenHelper,建立book表,在onCreate()中调用db.execSQL(CREATE_BOOK);建立数据库,这样保证建立数据库的同时又建立了表。
SQLite中Integer整型,real浮点型,blob二进制类型,text文本类型,primary key主键,autoincrement自增,
public class MyDatabaseHelper extends SQLiteOpenHelper {
public
static final String CREATE_BOOK="create table book(id integer primary key autoincrement,"
+"author text,price real,pages integer,name text)";
private
Context mContext;
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory
factory,int version){
super(context,name,factory,version);
mContext=context;
}
public void onCreate(SQLiteDatabase db)
{
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext,"Create Succeed",Toast.LENGTH_SHORT).show();
}
public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)
{
}
}
MainActivity中方法
public class MainActivity extends AppCompatActivity {
private Button createDatabase;
private MyDatabaseHelper dpHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dpHelper=new MyDatabaseHelper(this,"BookStore.db",null,1);
createDatabase=(Button)findViewById(R.id.createDatabase);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dpHelper.getWritableDatabase();
}
});
}
}
升级数据库
考虑到有时需要再创建一个表才可以,但是直接把代码加进去,由于之前数据库已经存在,就不会调用语句,所以要加相应的机制才能往一个数据库增加另一个表
MyDatabase中代码如下:
public class MyDatabaseHelper extends SQLiteOpenHelper {
public
static final String CREATE_BOOK="create table book(id integer primary key autoincrement,"
+"author text,price real,pages integer,name text)";
public static final String CREATE_CATEGORY="create table catagory(id integer primary key autoincrement," +
"catagory_name text,catagory_code integer)";
private
Context mContext;
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory
factory,int version){
super(context,name,factory,version);
mContext=context;
}
public void onCreate(SQLiteDatabase db)
{
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext,"Create Succeed",Toast.LENGTH_SHORT).show();
}
public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)
{
db.execSQL("drop table if exists book");
db.execSQL("drop table if exists catagory");
onCreate(db);
}
}
检测有没有BookStore.db这个数据库,没有就创建,db.execSQL(“drop table if exists book”);如果之前表已经存在,就删除,才能不显示错误,那么问题就是如何让程序调用onUpgrade()中的代码,在MainActivity中dpHelper=new MyDatabaseHelper(this,“BookStore.db”,null,2);之前的版本号为1,现在改为2,就达到了升级,从而可以重新创建数据库,两个表都存在。
怎么查看表已经建好了呢
adb是android SDK自带的一个调试工具,如果想在命令行直接使用,就要首先配置环境变量。Windows系统如下:此电脑-》属性-》高级-》环境变量,然后在系统变量找到Path并点击编辑-》新建,然后将SDK的
platform-tools目录配置进去就可以了
- Delete Link
![1534751921002.png](https://i.loli.net/2018/08/20/5b7a74c9a4221.png)
然后就可以使用adb工具了,使用时模拟器要开启
通过这些语句可以进入到数据库,adb schell :使用adb工具 ls:查看当前目录下所有文件 cd:进入到相应目录,根目录要加/ su root:获取管理员权限 sqlite3 后面加数据库名:打开数据库 .table:查看表 .schema:查看建表语句
![1535528286094.png](https://i.loli.net/2018/08/29/5b864d7cebac6.png)
![1535528687497.png](https://i.loli.net/2018/08/29/5b864f0cd8487.png)
添加数据
数据库基本操作CRUD,C(create)添加,R(retrieve)查询,U(update)更新,D(delete)删除,
借助SQLiteOpenHelper的getReadableDatabase()和 getWriteableDatabase()方法,返回一个SQLiteDatabase对象,可以实现CRUD操作,
添加数据 SQLiteDatabase提供了一个insert()方法,它接收三个参数,第一个是名字,第二个是未指定添加数据的情况下给某些可为空的数据列自动填充NULL,第三个是ContentValues对象,提供一系列的put方法重载,用于向ContentValues添加数据,只需将表对应列名和数据传入即可。
public class MainActivity extends AppCompatActivity {
private Button createDatabase;
private
Button addData;
private MyDatabaseHelper dpHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dpHelper=new MyDatabaseHelper(this,"BookStore.db",null,2);
createDatabase=(Button)findViewById(R.id.createDatabase);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dpHelper.getWritableDatabase();
}
});
addData=(Button)findViewById(R.id.addData);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=dpHelper.getReadableDatabase();
ContentValues values=new ContentValues();
//组装第一组数据
values.put("name","My Heart is hot");
values.put("author","jams");
values.put("pages","90");
values.put("price","34");
db.insert("Book",null,values);
values.clear();
//组装第二组数据
values.put("name","Honghong");
values.put("author","yuer");
values.put("pages","11");
values.put("price","0");
db.insert("Boook",null,values);
values.clear();
}
});
}
}
ContentValues对象的一个实例完成对要参加的数据的组装,insert()调用来插入
更改数据
update()方法,第一个参数表名,第二个参数是ContentValues对象,用来把更新数据组装进去,第三个和第四个指定操作序列,用于约束更新某一行或者几行的数据,不指定默认全修改
db.update("Book",contentValues,"name=?",new String[]{"Honghong"});
name=?,相当于SQL的where语句修改所有name=?的值,?表示占位符,具体内容就是第四个字符串
public class MainActivity extends AppCompatActivity {
private Button createDatabase;
private
Button addData;
private Button updateData;
private MyDatabaseHelper dpHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dpHelper=new MyDatabaseHelper(this,"BookStore.db",null,2);
createDatabase=(Button)findViewById(R.id.createDatabase);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dpHelper.getWritableDatabase();
}
});
addData=(Button)findViewById(R.id.addData);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=dpHelper.getReadableDatabase();
ContentValues values=new ContentValues();
//组装第一组数据
values.put("name","My Heart is hot");
values.put("author","jams");
values.put("pages","90");
values.put("price","34");
db.insert("Book",null,values);
values.clear();
//组装第二组数据
values.put("name","Honghong");
values.put("author","yuer");
values.put("pages","11");
values.put("price","0");
db.insert("Book",null,values);
values.clear();
}
});
updateData=(Button)findViewById(R.id.updateData);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=dpHelper.getWritableDatabase();
ContentValues contentValues=new ContentValues();
contentValues.put("price",12);
db.update("Book",contentValues,"name=?",new String[]{"Honghong"});
}
});
}
}
删除数据
public class MainActivity extends AppCompatActivity {
private Button createDatabase;
private
Button addData;
private Button updateData;
private Button deleteData;
private MyDatabaseHelper dpHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dpHelper=new MyDatabaseHelper(this,"BookStore.db",null,2);
createDatabase=(Button)findViewById(R.id.createDatabase);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dpHelper.getWritableDatabase();
}
});
addData=(Button)findViewById(R.id.addData);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=dpHelper.getReadableDatabase();
ContentValues values=new ContentValues();
//组装第一组数据
values.put("name","My Heart is hot");
values.put("author","jams");
values.put("pages","90");
values.put("price","34");
db.insert("Book",null,values);
values.clear();
//组装第二组数据
values.put("name","Honghong");
values.put("author","yuer");
values.put("pages","11");
values.put("price","0");
db.insert("Book",null,values);
values.clear();
}
});
updateData=(Button)findViewById(R.id.updateData);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=dpHelper.getWritableDatabase();
ContentValues contentValues=new ContentValues();
contentValues.put("price",12);
db.update("Book",contentValues,"name=?",new String[]{"Honghong"});
}
});
deleteData=(Button)findViewById(R.id.deleteData);
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=dpHelper.getWritableDatabase();
db.delete("Book","price>?",new String[]{"12"});
}
});
}
}
delete()方法要传入三个参数,第一个是表名,第二个和第三个用于限定删除某一行或几行的值,没有的话默认删除所有行。
查询数据
query()方法,有7个参数,此时我想吐······以下按顺序
query()方法参数 | 对应SQL部分 | 描述 |
---|---|---|
(1)table | from table_name | 表名 |
(2)columns | select column1,column2 | 列名 |
(3)selection | where column=value | 指定where约束条件 |
(4)selectionArgs | 为where占位符提供具体的值 | |
(5)groupby | group by column | 指定group by的列 |
(6)having | having column=value | 对group by后的结果进一步约束 |
(7)orderBy | order by column1,column2 | 指定查询结果的排序方式 |
调用query()方法会返回一个Cursor对象,查询的数据都从这里取出
queryData=(Button)findViewById(R.id.queryData);
queryData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db=dpHelper.getWritableDatabase();
//查询表中数据
Cursor cursor=db.query("Book",null,null,null,
null,null,null);
if(cursor.moveToFirst()){
//move cursor to first place,return whether the move is succeed,if the cursor is empty,return false
//遍历
do{
String name=cursor.getString(cursor.getColumnIndex("name"));
String author=cursor.getString(cursor.getColumnIndex("author"));
double price=cursor.getInt(cursor.getColumnIndex("price"));
int pages=cursor.getInt(cursor.getColumnIndex("pages"));
Log.d("MainActivity","name= "+name);
Log.d("MainActivity","author= "+author);
Log.d("MainActivity","price= "+price);
Log.d("MainActivity","pages= "+pages);
}while (cursor.moveToNext());
}
cursor.close();
}
});
使用SQL操作数据库
添加数据:
db.execSQL(“insert into Book(name,author,pages,price)values(?,?,?,?)”,new String[]{“A”,“B”,“34”,“12”});
更新数据:
db.execSQL(“update Book set price=?where name=?”,new String[]{“10”,“A”});
删除数据:
db.execSQL(“delete from Book where pages>?”,new String[]{“40”});
查询数据:
db.rawQuery(“select * from Book”,null);
整理自 郭霖《第一行代码》
最后
以上就是传统花卷为你收集整理的数据持久化存储数据持久化存储的全部内容,希望文章能够帮你解决数据持久化存储数据持久化存储所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复