Android数据存储、文件存储、SQLite数据库简单使用、 sharedPreferences存储(五)

您所在的位置:网站首页 sharepreferences保存文件的路径和扩展名 Android数据存储、文件存储、SQLite数据库简单使用、 sharedPreferences存储(五)

Android数据存储、文件存储、SQLite数据库简单使用、 sharedPreferences存储(五)

2023-09-06 06:44| 来源: 网络整理| 查看: 265

文章目录 5 数据存储5.1 数据的存储方式5.2 文件存储5.2.1 将数据存入文件中5.2.2 从文件中读取数据5.2.3 实战演练-保存QQ账号和密码(内部存储)5.2.4 实战演练-保存QQ账号和密码(外部存储-SD卡) 5.3 sharedPreferences存储5.3.1 将数据存入SharedPreferences中5.3.2 读取和删除数据5.3.3 实战演练—保存QQ账号和密码 5.4 SQlite数据库存储5.4.1 SQLite数据库的创建5.4.2 SQLite数据库的基本操作5.4.3 使用sql语句进行数据操作5.4.4 SQLite数据库中的事务5.4.5实战演练-通讯录

5 数据存储 5.1 数据的存储方式

在这里插入图片描述

补充

文件存储:读取方式和java中I/O程序是完全一样的SharedPreferences:这是Android提供的用来存储一些简单的配置信息的一种机制,用于存储一些应用程序的各种配置信息,入用户名,密码等SQlite数据库:是Android自带的一个轻量级的数据库,,一般使用它作为复杂数据的存储引擎,可以存储用户信息等ContentProvider:Android四大组件之一网络存储:需要Android网络数据包打交道,间数据存储到服务器上 5.2 文件存储

在这里插入图片描述

5.2.1 将数据存入文件中

1.内部存储

​ 内部存储值得是将应用程序中的数据以文件的形式存储到应用中(该文件默认位于data/data/< packagename > ,此时存储的文件会被所在的应用程序私有化,如果其他程序想要操作本应用程序中的文件,需要权限设置,当创建的应用程序被卸载的时候,期内部存储文件也会随之被删除。

示例代码:

参数:“name”表示文件名:“mode”表示文件的操作模式,也就是读写文件的方式 在这里插入图片描述 在这里插入图片描述

2.外部存储

​ 外部存储是将数据以文件的形式存储到一些外部设备上,例如SD卡或者设备内钱嵌的存储卡,属于永久性的存储方式(外部存储的文件通常位于mnt/sdcard目录下,不同的手机路径可能不同)外部的存储文件可以被其他应用程序所共享,当将外部存储文件设备连接计算机上时,这些文件可以被浏览,修改和删除,因此此方式不安全。

第一行:获取外部设备的状态

第二行:判断外部设备是否可用

加粗样式在这里插入图片描述

5.2.2 从文件中读取数据

1.读取内部存储中的文件数据

byte[] bytes= new byte[fis.available()]创建缓冲区,并获取文件的长度 在这里插入图片描述

2.读取外部存储中的文件数据

​ 首先需要读取外部设备(SD卡)的路径,并通过该路径读取相应的文件的数据 在这里插入图片描述 在这里插入图片描述

静态申请权限 在这里插入图片描述

动态申请权限

在这里插入图片描述

​ 申请正常权限时使用静态申请权限的方式即可,但对于一些涉及用户隐私的危险权限需要用户的授权后才可以使用,因此危险权限不仅需要在清单文件(AndroidManifest.xml)的< manifest >节点添加权限,还需在代码中动态申请权限,以动态申请SD卡的写权限为例:

​ requestPermissions()方法中包含3个参数,第1个参数为Context上下文,第2个参数需要申请的权限,第3个参数为请求码

在这里插入图片描述

​ 添加完动态申请权限后,运行程序,界面会弹出是否允许请求权限的对话框,有用户进行授权,如下图所示:

在这里插入图片描述

​ 上述图片内容为“是否允许访问设备上照片、媒体和文件的申请权限”DENY按钮表示拒绝,ALLOW按钮表示允许,当用户点击对话框中的“ALLow"按钮时,程序会执行动态申请权限回调方法onRequestPermissionsResult(),该方法中可以获去用户授予申请权限的结果。

​ 方法中包含三个参数:第一个参数requestCode表示请求码,permissions表示请求的权限,grantResults表示用户授予权限的结果。 在这里插入图片描述

5.2.3 实战演练-保存QQ账号和密码(内部存储)

使用文件存储的方式保存数据

在这里插入图片描述

FileSaveQQ.java

package com.example.administrator.saveqq; import android.content.Context; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class FileSaveQQ { //保存QQ账号和登录密码到data.txt 文件中 public static Boolean saveUserInfo(Context context, String account, String passwoed) { FileOutputStream fos = null; try { //获取文件的输出流对象fos fos = context.openFileOutput("data.txt", Context.MODE_PRIVATE); //将数据以字节码的方式写入data.txt文件中 fos.write((account + ":" + passwoed).getBytes()); return true; } catch (Exception e) { e.printStackTrace(); return false; } finally { try { if (fos != null) { fos.close(); } } catch (IOException e) { e.printStackTrace(); } } } //从data.txt文件中获取存储的QQ号账号密码 public static Map getUsetInfo(Context context){ String content = ""; FileInputStream fis = null; try { //获取文件的输入流对象 fis = context.openFileInput("data.txt"); //将输入流对象中的数据转换为字节码的形式 byte[] bytes= new byte[fis.available()]; fis.read(bytes);//通过read()方法读取字节码文件中的数据 content = new String(bytes);//将获取的字节码转换为字符串 Map map = new HashMap(); //将字符串以":"进行分割,然后形成一个数组的形式 String[] infos= content.split(":"); //讲述租的第一个数据放入userMap集合中 map.put("account",infos[0]); map.put("password",infos[1]); return map; } catch (Exception e) { e.printStackTrace(); return null; } finally { try { if(fis!=null){ fis.close(); } }catch (IOException e){ e.printStackTrace(); } } } }

MainActivity.java

package com.example.administrator.saveqq; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import java.util.HashMap; import java.util.Map; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private EditText et_account;//账号输入框 private EditText et_password;//密码输入框 private Button but_login;//登录按钮 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); //通过工具类FileSaveQQ中的getUserInfo()方法获取QQ帐号和密码信息 Map userInfo = FileSaveQQ.getUsetInfo(this); //Map userInfo = SPSaveQQ.getUserInfo(this); if(userInfo!=null){ et_account.setText(userInfo.get("account")); et_password.setText(userInfo.get("password")); } } private void initView() { et_account=findViewById(R.id.et_account); et_password=findViewById(R.id.et_password); but_login=findViewById(R.id.but_login); but_login.setOnClickListener(this); } @Override public void onClick(View view) { switch (view.getId()){ case R.id.but_login: //当点击“登录”按钮的时候,获取界面输入的账号和密码 String account = et_account.getText().toString().trim(); String password = et_password.getText().toString(); //检验输入的账号和密码是否为空 if(TextUtils.isEmpty(account)){ Toast.makeText(this,"你输入的账号为空",Toast.LENGTH_SHORT).show(); return; } if(TextUtils.isEmpty(password)){ Toast.makeText(this,"你输入的密码为空",Toast.LENGTH_SHORT).show(); return; } Toast.makeText(this,"登陆成功!",Toast.LENGTH_SHORT).show(); boolean isSave = FileSaveQQ.saveUserInfo(this,account,password); // boolean isSave = SPSaveQQ.saveUserInfo(this,account,password); if(isSave){ Toast.makeText(this,"保存成功",Toast.LENGTH_SHORT).show(); }else { Toast.makeText(this,"保存失败",Toast.LENGTH_SHORT).show(); } break; } } }

xml文件

5.2.4 实战演练-保存QQ账号和密码(外部存储-SD卡)

使用外部存储的方式保存数据(SD卡) 在这里插入图片描述 activity_main.xml文件

SDActivity

package com.example.administrator.test1; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Environment; import android.support.annotation.NonNull; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; public class SDActivity extends AppCompatActivity { private EditText nameEt, pwdEt; private TextView textView; private String data = "data.txt"; //写操作 public void mySave(View view) { //准备要保存的数据 String name = nameEt.getText().toString(); String pwd = pwdEt.getText().toString(); String state = Environment.getExternalStorageState();//获取外部设备状态 if (state.equals((Environment.MEDIA_MOUNTED))) { File SD = Environment.getExternalStorageDirectory(); File file = new File(SD, data); FileOutputStream fos = null; try { //获取文件字节输入流 fos = new FileOutputStream(file,true); //包装成字符输入流 OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fos); //创建字符缓冲区 BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter); //写入数据 bufferedWriter.write(name + "," + pwd); bufferedWriter.newLine();//写入换行符 bufferedWriter.flush();//刷新 fos.close(); outputStreamWriter.close(); bufferedWriter.close();//关闭流,释放资源 nameEt.setText(""); pwdEt.setText(""); } catch (Exception e) { e.printStackTrace(); } } } //读操作 public void myRead(View view) { String state = Environment.getExternalStorageState();//获取外部设备状态 if (state.equals(Environment.MEDIA_MOUNTED)) { File SD = Environment.getExternalStorageDirectory(); File file = new File(SD, data); //读取内存中的文件 try { FileInputStream fileInputStream = new FileInputStream(file); //将字节转换为字符输入流 InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream); //创建字符缓冲区 BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String msg = ""; textView.setText(""); while ((msg = bufferedReader.readLine()) != null) { textView.append(msg + "\n"); } fileInputStream.close(); inputStreamReader.close(); bufferedReader.close();//关闭流,释放资源 } catch (Exception e) { e.printStackTrace(); } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestCode==1){ for(int i =0;i Toast.makeText(SDActivity.this,"申请成功",Toast.LENGTH_SHORT).show(); } else { Toast.makeText(SDActivity.this,"申请失败",Toast.LENGTH_SHORT).show(); } } } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); nameEt = findViewById(R.id.name); pwdEt = findViewById(R.id.pwd); textView = findViewById(R.id.tv); ActivityCompat.requestPermissions(SDActivity.this,new String[] {"android.permission.WRITE_EXTERNAL_STORAGE"},1); } }

最后还需要在AndroidManifest.xml文件的< manifest >标签中添加

5.3 sharedPreferences存储

在这里插入图片描述

5.3.1 将数据存入SharedPreferences中

第一步:获取sp对象,参数data表示文件名,MODE_PRIVATE表示文件操作模式

由于该对象本身只能获取数据,不能对数据进行存储和修改,因此需要调用SharePreferences类的edit()的方法获取可编辑的Editor对象。 在这里插入图片描述

editor.commit(); //提交修改

5.3.2 读取和删除数据

在这里插入图片描述 SharePreferences本身是一个接口,无法直接创建该实例,只能通过Context获取SharePreferences实例对象:SharePreferences preference = context.getSharePreferences(name,mode); 在这里插入图片描述

获取数据的key值与存入数据的key值数据类型要一致,否则找不到指定数据

保存SharedPreferences的key值是,使用静态变量保存,以免操作是写错,如private final String key= “itcast”。

5.3.3 实战演练—保存QQ账号和密码

使用SharedPreferences存储的方式保存数据

SPSaveQQ.java

package com.example.administrator.saveqq; import android.content.Context; import android.content.SharedPreferences; import java.util.HashMap; import java.util.Map; public class SPSaveQQ { public static boolean saveUserInfo(Context context,String account,String password){ SharedPreferences sp = context.getSharedPreferences("data",Context.MODE_PRIVATE); SharedPreferences.Editor editor= sp.edit(); editor.putString("account",account); editor.putString("password",password); editor.commit(); return true; } public static Map getUserInfo(Context context){ SharedPreferences sp = context.getSharedPreferences("data",Context.MODE_PRIVATE); String account = sp.getString("account",null); String password = sp.getString("password",null); Map map = new HashMap(); map.put("account",account); map.put("password",password); return map; } }

xml文件和5.2.3节相同,这里省略。

MainActivity.java

这里面修改两句代码即可(调用的代码)分别是5.2.3节中的第27行代替26行,和60行代替59行即可。

如果想要查看你存储的文件是否保存了数据,可以在以下位置找到。

运行你的项目

在右下角找到Device File Explorer文件(便于观察我将图片旋转了一下)在这里插入图片描述

打开data文件中的data文件 在这里插入图片描述

在data文件中找到你的项目文件 在这里插入图片描述

上面两个分别就是上述两种存储方式生成的文件,可以右键,然后点击Save保存至桌面进行查看。

5.4 SQlite数据库存储

​ 前面介绍了如何使用文件进行存储和SharedPreferences存储数据,这两种方式适合存储简单数据,当你需要存储大量的数据的时候,显然不适合,为此Android提供了一个SQLite数据库,它可以存储应用程序中的大量数据,并对数据进行管理和维护。

SQLite非常健壮,每天可以处理多达100000次点击率web站点,甚至可以处理上述数字的10倍负载。SQLite是一个轻量级别的数据库,在一些语句的处理性能上要比MySql等数据库要快,对于内存有限的Android手机设备而言,当然是对时间空间要求越低的数据库引擎越好。SQLite支持多数SQL92标准,可以在所有主流的操作系统上运行,并支持大多数的计算机语言。 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 5.4.1 SQLite数据库的创建 SQLiteDatabase代表一个数据库(底层就是一个数据库文件)。使用SQLiteOpenHelper类,获取SQLiteDatabase对象。只需要创建一个类继承SQLiteOpenHelper类,在该类中重写onCreate()方法和onUpgrade()方法即可super()调用父类SQLiteOpenHelper,并传入4个参数,分别表示上下文对象,数据库名称,游标工厂(通常是null),数据库版本onGrate(SQLiteDatabase db)方法是在数据库第一次创建的时候调用的,此方法通常用于初始化结构,当调用 SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法 获取用于操作数据库的SQLiteDatabase实例时,如果数据库不存在,Android 系统会自动生成一个数据库,接着调用onCreate方法onCreate方法在初次 生成数据库时才会被调用,重写onCreate方法,可以生成数据库表结构及添加 一些应用使用到的初始化数据。onUpgrade()方法在数据库版本号增加时调用,如果版本号不增加,此方法不调用。

在这里插入图片描述

扩展 SQLite Expert Personal可视化工具

1.在Android系统中,数据库创建完成后是无法直接对数据进行查看的,想要查看需要使用SQLite Expert Personal可视化工具,可在官网(点击查看)中下载SQLite Expert Personal工具

在这里插入图片描述

2.接下来通过SQLite Expert Personal查看已将创建好的数据库文件,可在Device File Explorer视图中找到数据库文件所在的目录【data】–>【data】–>【项目包名全路径】–>【databases】

3.数据库文件是.db为扩展名,右键点击【Save As】将文件导入到指定目录下

4.在SQLite Expert Personal工具中点击【File】–>【Open Database】选项,选择你想要查看的数据库文件

5.4.2 SQLite数据库的基本操作

1.新增数据 (inset) 在这里插入图片描述

通过getWritableDatabase()方法得到SQLiteDatabase对象,然后获取ContentValues对象中,最后调用insert()方法将数据插入到information表中**inset()**方法接收3个参数,第一个参数是数据库表的名称,第二个参数是表示如果发现将要插入的行行为为空时,会将这个列名的值设为null,第三个参数为ContentValues对象ContentValues类似于Map类,通过键值对元素的形式将数据存入,这里的key值表示插入数据库的列名,value表示要插入的数据最后一定要使用close()方法将它关闭,否则数据库连接会一直存在,不断消耗内存,当系统内存不足的时候获取不到SQLiteDatabase对象,并且会报出数据库未关闭异常。 在这里插入图片描述

2.删除数据(delete)

删除操作不需要使用ContentValue来添加数,而是使用一个字符串和一个字符数组来添加参数名和参数值

在这里插入图片描述

3.修改数据(update)

update()方法中有四个参数,第一个参数表示数据库表名称,第二个参数是修改后的数据,第三个参数表示要修改的数据的查询条件,第四个参数是表示查询条件的参数。

在这里插入图片描述

4.查询数据(query)

query方法中有7个参数,第一个参数表名称,第二个参数表示查询的列名,第三个参数表示接收查询条件的子句,第四个参数表示接收查询子句对应的条件值,第五个参数值表示分组方式,第六个阐释是接收having条件,即定义的过滤器,第七个参数表示排序的方式getCount()方法获取查询到的结果总数moveToNext()方法移动游标指向下一行数据getString()方法传入列名获取对应的数据

在这里插入图片描述

5.4.3 使用sql语句进行数据操作

在这里插入图片描述

查询操作有所不同,由于execSQL()方法没有返回值,因此查询操作使用的是rawQuery()方法,返回一个结果集Cursor

5.4.4 SQLite数据库中的事务

在这里插入图片描述

原子性(Atomicity):表示事务是一个不可再分割的工作单位,实务中的操作要么都成功,要么都失败回滚。

一致性(Consistency):表示事务开始之前和结束之后,数据的完整性没有被破坏,也就是说数据库事务不能破坏关系型数据的完整性以及业务逻辑上的一致性

隔离性(Isolation):表示并发的事务是相互隔离的,也就是一个事物内部的操作都必须封锁起来,不被其他事务影响到

持久性(Durability):表示事务一旦提交后,该事务对数据做的更改变持久保存在数据库中,并不会回滚,即使出现断电的事故,也不会影响数据库中的数据

例: 在这里插入图片描述

5.4.5实战演练-通讯录

在这里插入图片描述

layout_tx.xml文件

tx_test.java文件

package com.example.administrator.saveqq; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class tx_test extends AppCompatActivity implements View.OnClickListener { private EditText mEtName; private EditText mEtPhone; private TextView mTvShow; private Button mBtnAdd; private Button mBtnQuery; private Button mBtnUpdate; private Button mBtnDelete; MyHelper myHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_tx); myHelper = new MyHelper(this); init(); } private void init() { mEtName= findViewById(R.id.et_name); mEtPhone = findViewById(R.id.et_phone); mTvShow = findViewById(R.id.tv_show); mBtnAdd = (Button) findViewById(R.id.btn_add); mBtnQuery = findViewById(R.id.btn_query); mBtnUpdate = findViewById(R.id.btn_update); mBtnDelete = findViewById(R.id.btn_delete); mBtnAdd.setOnClickListener(this); mBtnQuery.setOnClickListener(this); mBtnUpdate.setOnClickListener(this); mBtnDelete.setOnClickListener(this); } @Override public void onClick(View view) { String name,phone; SQLiteDatabase db; ContentValues values; switch (view.getId()){ case R.id.btn_add ://添加数据 //获取界面上的name,phone name = mEtName.getText().toString(); phone = mEtPhone.getText().toString(); db = myHelper.getWritableDatabase();//获取可读写的SQLiteDatabase对象 values = new ContentValues();//创建ContentValues对象 values.put("name",name);//将数据添加到ContentValues对象 values.put("phone",phone); db.insert("information",null,values); Toast.makeText(this,"信息已添加!",Toast.LENGTH_SHORT).show(); db.close(); break; case R.id.btn_query ://查询数据 db = myHelper.getReadableDatabase(); Cursor cursor = db.query("information",null,null,null, null,null,null); if(cursor.getCount()!=0){//判断cursor里面有多少调数据,如果没有,就不进入循环 mTvShow.setText("");//初始化为空 while (cursor.moveToNext()){ //append逐个添加数据 mTvShow.append("name:"+cursor.getString(1)+";"+"Tel"+cursor.getString(2)+"\n"); } } cursor.close(); db.close(); break; case R.id.btn_update ://修改数据 db = myHelper.getWritableDatabase(); values = new ContentValues();//要修改的数据 values.put("phone",mEtPhone.getText().toString()); //更新并返回行数 db.update("information",values,"name=?", new String[]{mEtName.getText().toString()}); Toast.makeText(this,"信息已经修改",Toast.LENGTH_SHORT).show(); db.close(); break; case R.id.btn_delete ://删除数据 db = myHelper.getWritableDatabase();//获取可读写的SQLiteDatabase对象 //删除全部内容 db.delete("information",null,null); Toast.makeText(this,"信息已经删除!",Toast.LENGTH_SHORT).show(); //重置TextView为空 mTvShow.setText(""); db.close(); break; } } class MyHelper extends SQLiteOpenHelper { public MyHelper(Context context) { super(context,"itcast.db",null,2); } @Override public void onCreate(SQLiteDatabase sqLiteDatabase) { sqLiteDatabase.execSQL("CREATE TABLE information(_id INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20),phone VARCHAR(20))"); } @Override public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) { } } }

后续笔记会持续更新,希望大家给个一键三连!!!!! 点击前往Android开发总目录 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3