Android:数据存储

140 阅读6分钟

image.png

我们都一样,既然无可选择,只得尽力而为。

自身强大,才能为别人排忧解难;内心通透,才能为他人指点迷津。

数据存储方式

数据,如今是数据大时代,谁拥有数据,谁就能掌握未来,在手机APP中存在着你的大量数据信息,大数据的可以根据你的数据通过算法得出你的生活规律等。 在Androi系统中有5种存储方式,每种方式都有其不同的特点。

  • 文件存储:以I/O流形式将数据存入手机内存或者sd卡,可以存储大数据,如音乐、图片或许视频等。

  • ShardedPreferences:它本质上是一个xml文件,以Map<Object,Object>形式存入手机内存中。常用于存储比较简单的参数设置,如qq登录账号密码的存储、窗口功能状态的存储等,使用方便、简单。

  • SQLite数据库:SQLite是一个轻量级、跨平台的数据库。数据库中所有信息都存储在单一文件内,占用内存小,并且支持SQL语法,是项目中经常被采用的一种存储方式,通常用于存储用户信息等。

  • ContentProvider:又称内容提供者,是Android四大组件之一,以数据库的形式存入手机内存,可以共享自己的数据给其他应用使用。相对其他对外共享数据的方式而言,ContentProvider统一了数据访问方式,使用起来更加规范。

  • 网络存储:把数据存储到服务器,不存在本地,使用的时候直接通过网络获取,避免了手机端信息丢失以及其他安全隐患。

本篇主要介绍Android中实现数据存储的3种方式:文件存储、ShardedPreferences存储、SQLite数据库

文件存储

文件存储是Android中最基本的一种数据存储方式,它与java中文件存储类似,搜索通过I/O流的形式把数据原封不动存储到文件中。不同的是Android中存储分为外部存储内部存储

内部存储

内部存储使用的是Context提供的openFileOutput()方法和openFileInput()方法,来进行读写操作。

在存储数据时openFileOutput有4种状态:

  1. MODE_PRIVATE:该文件只能被当前程序读写,默认的操作模式。

  2. MODE_APPEND:该文件的内容可以追加,常用的一种模式

  3. MODE_WORLD_READABLE:该文件内容可以被其它文件读取,安全性低,通常不使用。

  4. MODE_WORLD_WRITEABLE:该文件内容可以被其他程序写入,安全性低,通常不使用。

初始化:

private EditText editText;//内容输入
private TextView textView;//存放读取内容
private Button btn,button2;//写入;读取

String fileName="data.txt";//创建文件
String content="";//保存数据
private FileOutputStream fileOut;//文件输出流
private FileInputStream fileINput;//文件输入流

写入内容:

//        写
     btn.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View view) {
             content=editText.getText().toString();
             try {
                 fileOut=openFileOutput(fileName,MODE_PRIVATE);
                 fileOut.write(content.getBytes());
                 fileOut.close();//写完一定要关流,不然会造成内存泄漏
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
     });

读取文件内容:

//        读
        button2.setOnClickListener(view->{
            try {
                fileINput=openFileInput("data.txt");
                byte[] buffer=new byte[fileINput.available()];//获取到文件的可用
                fileINput.read(buffer);
               String s=new String(buffer);
               textView.setText(s);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

效果展示:

tutieshi_326x618_19s.gif

外部存储

外部文件是指将文件存储到一些外围设备上例如SD卡或者设备内嵌存储卡等。 由于外部存储设备可以被移除、丢失或者处于其他状态因此使用外围设备前必须使用Environment类的getExternalStorageStatel()方法确认设备是否可用。

写:

button3.setOnClickListener(view->{
//            判断有没有外部设备
            if (state.equals(Environment.MEDIA_MOUNTED)){
                //获得外部存储目录
                File SD=Environment.getExternalStorageDirectory();//自动获取外部存储路径
                File file=new File(SD,"data2.txt");//创建文件
                String data="HellWorld";
                FileOutputStream fileOut;//文件输出流;
                try {
                    fileOut= new FileOutputStream(file);//文件输出流;
                    fileOut.write(data.getBytes());
                    fileOut.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

读取:

button4.setOnClickListener(view->{
    File SS=Environment.getExternalStorageDirectory();
    File fil=new File(SS,"data2.txt");
    FileInputStream fis;
    try {
        fis=new FileInputStream(fil);
        BufferedReader br=new BufferedReader(new InputStreamReader(fis));
        String datas=br.readLine();
        Log.d("TAG", datas);
        fis.close();
        
    } catch (Exception e) {
        e.printStackTrace();
    }
});

ShardedPreferences存储

它屏蔽了对底层文件 的操作,通过为程序开发人员提供简单的编程接口,实现以最简单的方式对数据进行永久保存。这 种方式主要对少量的数据进行保存,比如对应用程序的配置信息、手机应用的主题、游戏的玩家积 分等进行保存。

调用该方法来保存数据:

private SharedPreferences.Editor editor;//调用该方法

通过点击按钮保存数据到SharedPreferences中:

//        写入数据
        btn.setOnClickListener(view->{
            username=editText.getText().toString();
            password=editpassword.getText().toString();
            editor.putString("username",username);
            editor.putString("paw",password);
            editor.commit();//提交
        });

从SharedPreferences中读取数据通过弹窗提示显示:

/       读取数据
        btn2.setOnClickListener(view -> {
            SharedPreferences sp=getSharedPreferences("mr",MODE_PRIVATE);
//            参数2:默认值
            String user=sp.getString("username","暂无保存数据");
            String pawss=sp.getString("paw","暂无保存数据");
            AlertDialog.Builder builder=new AlertDialog.Builder(this);
            builder.setTitle("显示保存的信息")//设置标题;
                    .setMessage("账号:"+user+"\n"+"密码:"+pawss)//设置消息内容;
                    .setCancelable(false)//设置可取消,
                    .setPositiveButton("知道了", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int i) {
                            dialog.cancel();
                        }
                    });//建立按钮
            builder.create().show();//创建,显示

        });


    }

效果展示

tutieshi_324x610_24s.gif

信息保存成功后,保存账号与密码的mr.xml文件将被保存在“data\data<项 目资源包名>\shared_prefs\”目录下。

image.png

SQLite

Android 提供了 SQLiteDatabase,用于表示一个数据库,应用程序只要获得了代表数据库 的 SQLiteDatabase 对象,就可以通过 SQLiteDatabase 对象来创建数据库.

创建数据库:可以创建一个新的类来调用,也可以在Activity中创建一个内部类使用

package com.example.mysqlist.sql;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

import androidx.annotation.Nullable;

public class DatabaseHelper extends SQLiteOpenHelper {

    private static final String TAG = "detectionDB";

    //    必要的构造函数
    public DatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    /**
     * @param db
     * 创建数据库,对数据库的操作
     */
    @Override
    public void onCreate(SQLiteDatabase db) {
//        创建新表
        String sql="CREATE TABLE gafuli(_id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "CO VARCHAR(20)," +
                "CO2 VARCHAR(20)," +
                "HC VARCHAR(20)," +
                "O2 VARCHAR(20)," +
                "Noxygen VARCHAR(20)," +
                "Speed INTEGER," +
                "OilTemp VARCHAR(20))";
        db.execSQL(sql);

        Log.i(TAG, "创建数据库成功!");
    }

    /**
     * @param sqLiteDatabase
     * @param oldVersion
     * @param newVersion
     * 更改数据库版本的操作
     */
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        Log.e(TAG,"update Database OK!");
    }

    /**
     * @param db
     * 每次成功打开数据库后首先被执行
     */
    @Override
    public void onOpen(SQLiteDatabase db) {
        Log.d(TAG, "数据库打开成功!");
        super.onOpen(db);
    }

}

在MainActivity中调用创建数据库:

private DatabaseHelper dbHelper;//数据库类
private SQLiteDatabase db;//获取数据库

//参数1:上下文;参数2:数据库名;参数3:什么模式;参数4:数据库版本号
                dbHelper=new DatabaseHelper(
                        MainActivity.this,
                        "detectionDB.db",
                        null,
                        1);
//得到一个可读的数据库对象
                db=dbHelper.getReadableDatabase();

插入数据库:

 try {
                    dbHelper=new DatabaseHelper(MainActivity.this,"detectionDB",null,1);
                    //得到一个可写的数据库对象
                    db=dbHelper.getWritableDatabase();
//                向ContentValues对象中存放数据:以键值对的方式
                    ContentValues cv=new ContentValues();
                    cv.put("CO",CoEdt.getText().toString());
                    cv.put("CO2",Co2Edt.getText().toString());
                    cv.put("HC",HCEdt.getText().toString());
                    cv.put("O2",O2Edt.getText().toString());
                    cv.put("Noxygen",NoEdt.getText().toString());
                    cv.put("Speed",SpeedEdt.getText().toString());
                    cv.put("OilTemp",OilTempEdt.getText().toString());
//                将数据插入表中
                    db.insert("gafuli",null,cv);
//                关闭数据库
                    db.close();
                    Toast.makeText(this, "插入数据成功", Toast.LENGTH_SHORT).show();
                } catch (Exception e) {
                    Toast.makeText(this, "插入数据失败", Toast.LENGTH_SHORT).show();
                }

查询数据库:

//查询数据
dbHelper=new DatabaseHelper(MainActivity.this,"detectionDB",null,1);
db=dbHelper.getReadableDatabase();//可读数据
String sql="SELECT * FROM gafuli";
cursor=db.rawQuery(sql,null);//查询表的全部数据

SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.acyivity,cursor,
        new String[]{"_id","CO","CO2","HC","O2","Noxygen","Speed","OilTemp"},
        new int[]{R.id.textView, R.id.textView2, R.id.textView3,R.id.textView4,R.id.textView5,R.id.textView6, R.id.textView7, R.id.textView8},
        CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
itemSQL.setAdapter(adapter);
db.close();

效果演示,因为之前测试已经存储了一些内容在里面。还有因为分配页面的不均匀导致显示的时候因为字体和空间原因会出现偏差和显示不齐全的问题

tutieshi_394x756_41s.gif

人间的事,只要生机不灭,即使重遭天灾人祸,暂被阻抑,终有抬头的日子。