数据持久化存储

数据持久化存储

主要有以下三种方式进行数据持久化存储

一.文件存储

存储文件

最基本的存储方式,会把存储内容原封不动保存到文件中,主要存储二进制数据和简单的文本数据。如果想存储复杂的数据,就要有自己的格式规范

在布局文件中添加一个EditText来输入东西

实现过程就是:在onCreate()方法中创建一个EditText的实例,然后再重写onDestory()方法,这样确保在活动销毁前一定会调用这个实例,在onDestroy()方法中,定义一个string类来获取输入的内容,然后调用save()方法来完成存储文件功能。save()中,首先通过openFileOutput()方法得到一个FileOutputStream对象,然后再借助它构成一个OutputStreamWriter对象,接着再使用OutputStreamWriter构建出一个BufferedWriter对象,这样就可以通过BufferedWriter写入文本了。

openFileOutput()方法,是Context类提供的,接受两个参数,第一个参数是文件名,不用包含路径,第二个参数是操作模式,主要有两种模式,MODE_PRIVATE是默认操作模式,同文件名,覆盖原内容,MODE_APPEND同文件名,追加内容,不存在就新创建文件。

mainActivity中代码如下:

package com.example.tingyu.filepersistenceteat;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.EditText;

import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;

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()方法将光标移动到末尾以便继续输入

扫描二维码关注公众号,回复: 4007554 查看本文章
package com.example.tingyu.filepersistenceteat;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.EditText;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

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()方法将数据提交,从而完成存储。

package com.example.tingyu.sharedpreferencetest;

import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

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)

读取

同样用按钮点击事件来实现,通过打印日志看效果。

package com.example.tingyu.sharedpreferencetest;

import android.content.SharedPreferences;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

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自增,

package com.example.tingyu.database;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

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中方法

package com.example.tingyu.database;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

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中代码如下:

package com.example.tingyu.database;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

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目录配置进去就可以了

![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添加数据,只需将表对应列名和数据传入即可。

package com.example.tingyu.database;

import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

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=?的值,?表示占位符,具体内容就是第四个字符串

package com.example.tingyu.database;

import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

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"});
            }
        });
    }
}

删除数据

package com.example.tingyu.database;

import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

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);

整理自 郭霖《第一行代码》

猜你喜欢

转载自blog.csdn.net/ytingyu/article/details/83501474