android数据的储存、文件的储存、SharedPreferences储存、SQLite的基本用法

news2024/11/28 21:45:19

一、文件的储存

1、将数据储存到文件中

Context类中提供了openfileOutput()方法,用来获取一个文件流,这个方法接收两个参数,第一个参数是文件名,在文件创建的时候使用的就是这个名称,注意这里指定的文件名不可以包含路径,因为所有的文件都是默认存储到/data/data/iles/目录下的。第二个参数是文件的操作模式,主要有两种模式可选,MODE_PRIVATE和MODE_APPEND。

MODE_PRIVATE:会覆盖源文件数据

MODE_APPEND:在源文件后追加数据

将文本内容保存到文件的代码展示:

public void save(){
    String Data = "Data on save";
    //创建一个文件流
    FileOutputStream out = null;//创建一个缓存流
        BufferedWriter writer  = null;

    try {
        //打开这个文件流
        out = openFileOutput("data",MODE_PRIVATE);
        //将文件流转化转换流,在通过转换流得到缓存流
        writer = new BufferedWriter(new OutputStreamWriter(out));

        //通过缓存流写入数据
        writer.write(Data);
    }catch (IOException e){
        e.printStackTrace();
    }finally {
        if(writer != null){
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述

2、从文件中读取数据

Context类中还提供了一个openFileInput()方法,用于读取文件。只接收一个参数及要读取的文件名。

读取数据代码如下:

    private String load() {
        FileInputStream fileInputStream = null;
        BufferedReader bufferedReader = null;
        StringBuilder builder = new StringBuilder();

        try {
            fileInputStream = openFileInput("data");
            bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));
            String leng = "";
            while ((leng = bufferedReader.readLine()) != null){
                builder.append(leng);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(bufferedReader != null){
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return builder.toString();
    }
  • bufferedReader.lines()用于处理大型文件,通过返回一个字符串流(Stream<String>)来处理每一行数据。直接返回所有内容,不需要判读是否读取结束。

  • bufferedReader.readLine()用于读取文件的一行文本数据,并返回一个字符串。读取结束时返回null

  • bufferedReader.read()用于逐个读取字符的整数值,并需要自己处理字符的连接以获取完整的文本数据。这种方法更适合处理二进制数据或特殊的文本处理场景。

  • int len = 0; //文件读取长度
    byte[] careBuffer = new byte[1024]; //1kb
    while ((len = buff.read(careBuffer)) != EOF) {
        buff1.write(careBuffer, 0, len);
    }
    

二、SharedPreferences

1、获取SharedPreferences对象的两种方式

1.1 Context类中的getSharedPreferences()

该方法接受两个参数,第一个参数是文件名,第二个参数是MODE_PRIVATE和直接传入0的效果一样,表示只有当前程序才可以对Sharedpreferences进行读写操作。

1.2 Activity类中的getPreferences()方法

这个方法和Context中的getSharedPreferences()方法很相似,不过它只接收一个操作模式参数(MODE_PRIVATE),因为使用这个方法时会自动将当前活动的类名作为SharedPreferences的文件名。

2、将数据储存到SharedPreferences

1.1实现步骤

a、得到SharedPreferences对象以后调用edit()方法获取一个内部类的SharedPreferences.Editor.

b、向Editor对象中添加数据,例如添加字符串就使用putString(),添加int类型数据就使用putInt()

c、使用apply()方法提交数据完成储存

2.2 实现代码

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    editText = findViewById(R.id.edit);

    SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();

    editor.putString("username", "lukecc0");
    editor.putString("age", "1");
    editor.putBoolean("married", false);

    editor.apply();

}

image-20230726104314471

username就相当于key,在SharedPreferences中,每个数据都有一个关联的键(key),通过这个键可以访问相应的值(value)。通过SharedPreferences.Editor对象,你可以添加、编辑或删除这些键值对。

3、从SharedPrefrences中读取数据

SharedPreferences对象中提供了一系列的get方法,用于对存储的数据进行读取,每种get方法都对应SharedPreferences.Editor中的一种put方法

比如读取一个布尔型数据就使用getBoolean()方法,读取一个字符中就使用getString()方法。

这些get方法都接收两个参数,第一个参数是键,传入存储数据时使用的键就可以得到相应的值了,第二个参数是默认值,即表示当传入的键找不到对应的值时会以什么样的默认值进行返回。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    editText = findViewById(R.id.edit);
    Button button = findViewById(R.id.button);

    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //读取数据
            SharedPreferences pref = getSharedPreferences("data",MODE_PRIVATE);
            editText.setText(pref.getString("username","admin")+"\n"
                             +pref.getString("age","0")+"\n"+pref.getBoolean("marride",false));
        }
    });

}

当点击按钮后就会出现数据,如下图:

image-20230726105720243

image-20230726105730897

三、SQLite

1、创建数据库

建立一个MyDatabase类继承SQLite

重写onCreate、onUPgrade方法

获得MyDatabase的实例

选择打开方式打开

SQLiteOpenHelper是一个抽象类,这意味着如果我们想要使用它的话,就需要创建一个自己的帮助类去继承它。SQLiteOpenHelper中有两个抽象方法,分别是onCreate()onUpgrade()我们必须在自己的帮助类里面重写这两个方法,然后分别在这两个方法中去实现创建、升级数据库的逻辑。

SQLiteOpenHelper中还有两个重要的实例方法,getReadableDatabasegetwirtableDatabase,这两个方法的可以创建或打开一个数据库,不同的是如果磁盘满了的情况下:

  • getReadableDAtabase方法返回的对象将以只读的方式打开数据库

  • getWritableDatabase方法将会出现异常

SQL建立表语句:

create table Book(
    id integer primary key autoincrement,
    author text,
    price real,
    pages integer,
    name text)

integer表示整型,real表示浮点型,txt表示文本类型,blob表示二进制类型,primary key设置主键,autoincrement显示id是自动增长的。

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 MyDatabaseHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        //创建数据库,参数为建库语句
        sqLiteDatabase.execSQL(CREATE_BOOK);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    }
}

**public SQLiteOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version)**构造方法的含义:

  • context:Android 应用程序的上下文
  • name: 这是要创建或打开的数据库的名称。如果数据库不存在SQLiteOpenHelper 会创建一个新的数据库文件,如果数据库已经存在,它将尝试打开该数据库。这里传入的数据库名称可以是一个字符串,表示数据库的名称。
  • factory:这是一个用于创建游标对象的工厂。游标是用于查询数据库并遍历结果集的对象。通常情况下,你可以传入 null
  • version:这是数据库的版本号。当应用程序需要进行数据库结构的更改时,你需要增加数据库版本号。

在MainActivity中使用数据库

public class MainActivity extends AppCompatActivity {

    private MyDatabaseHelper dbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //创建一个数据库的帮助类
        dbHelper = new MyDatabaseHelper(this,"BookStore.dp",null,2);

        Button button =findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                创建数据库
                dbHelper.getWritableDatabase();
            }
        });
    }
}

那么如何看到这个数据库呢?请参考android官方开发文档

查询数据库

2、更新数据库

使用onUpgrade更新数据库。

例如现在需要再建立一个表,如果已经建好表的情况下,onCreate是不会再继续执行的。因此这样的在onCreate中直接加入建表语句是不行的。

private static final String Category = "create table Category("
    + "id integer primary key autoincrement,"
    + "Category_name text,"
    + "Category_code integer)";

@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
    //创建数据库,参数为建库语句
    sqLiteDatabase.execSQL(CREATE_BOOK);
    sqLiteDatabase.execSQL(Category);
    Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}

因此我们需要在onUpgrade中编写代码逻辑。

drop table if exists:是一个 SQL 语句,用于删除表,使用这个语句时要小心,因为一旦执行,表中的所有数据将被永久删除,并且无法恢复。这通常用于在数据库中不再需要某个表时进行清理。

@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    sqLiteDatabase.execSQL("drop table if exists Book");
    sqLiteDatabase.execSQL("drop table if exists Gategory");

    onCreate(sqLiteDatabase);
}

在上述这段代码中,会先删除两个表,然后重新创建两个表。主要原表的数据将会被清空。如何实现不清空原表数据?如果有SQL基础请看下面这段代码,没有请自行忽略这个问题。

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        // 备份旧表数据
        sqLiteDatabase.execSQL("CREATE TABLE Book_backup AS SELECT * FROM Book");

        // 删除旧的 Book 表
        sqLiteDatabase.execSQL("DROP TABLE IF EXISTS Book");

        // 创建新的 Book 表
        sqLiteDatabase.execSQL(CREATE_BOOK);

        // 将备份表数据复制到新表中
        sqLiteDatabase.execSQL("INSERT INTO Book (id, author, price, pages, name) SELECT id, author, price, pages, name FROM Book_backup");

        // 删除备份表
        sqLiteDatabase.execSQL("DROP TABLE IF EXISTS Book_backup");
        

        Toast.makeText(mContext, "Database upgraded successfully", Toast.LENGTH_SHORT).show();
    }

接下来我们需要让onUpgrade 可以执行,在使用MyDatabase的构造方法时,修改最后一个传递参数version,他显示的数据库版本,我们之前使用的是1,现在传递一个比1大的数即可。

3、添加数据——insert

前面我们已经知道,调用SQLiteOpenHelpergetReadableDatabase()getwritable-Datābase()方法是可以用于创建和升级数据库的。

不仅如此,这两个方法还都会返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行CRUD操作了。

**SQLiteDatabase提供了一个insert方法,用于添加数据。**它需要三个参数。

第一个参数是表名,我们需要往哪个表加入数据就写哪个表名。

第二个参数用于在未指定添加数据的情况下给某些可为空的列自动赋值NULL,一般我们用不到这个功能,直接传入null即可。

第三个参数是一个ContentValues对象,它提供了一系列的put()方法重载,用于向ContentValues中添加数据,只需要将表中的每个列名以及相应的待添加数据传入即可。

binding.button1.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        ContentValues values = new ContentValues();

        //将数据保存起来,第一条数据
        values.put("name","This is one");
        values.put("author","dow");
        values.put("pages",23);
        values.put("price",12);

        //添加数据
        db.insert("Book",null,values);

        //将数据保存起来,第二条数据
        values.put("name","This is two");
        values.put("author","dow1");
        values.put("pages",231);
        values.put("price",112);

        db.insert("Book",null,values);
    }
});

点击这个按钮,我们每次向数据库中保存两条数据。

image-20230726164911477

为什么没有给id赋值?因为我们在建表时已经设置为了自动增长

id integer primary key autoincrement

4、更新数据——updata

binding.button2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put("price",110);
        //更新所有名为This is one的书
        db.update("Book",values,"name = ?",new String[]{"This is one"});
    }
});

5、删除数据——delete

//删
binding.button3.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        db.delete("Book","pages > ?",new String[]{"200"});
    }
});

指定删除pages大于200的书。

6、查询数据——query

query具有7个参数

image-20230726180033182

它会返回一个Cursor对象,这个对象中保存了数据库的信息,查询的所有数据都从这个对象中取出。

//查
binding.button4.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        SQLiteDatabase db = dbHelper.getWritableDatabase();
        Cursor cursor = db.query("Book",null,null,null,null,null,null);

        if(cursor.moveToFirst()){
            do {
                String name = cursor.getString(cursor.getColumnIndex("name"));
                int price = cursor.getInt(cursor.getColumnIndex("price"));

                Log.d("TAG1",name);
                Log.d("TAG1",price+"");

            }while (cursor.moveToNext());
        }
    }
});

image-20230726180206424

moveToFirst方法,将数据的指针移到开头第一行的位置。然后进入一个循环读取数据,在while中使用moveToNext方法每次将数据指针向下移动一位。getColumnIndex方法用于获取指定某一列在表中的位置。

如下表,先获取了name、price的位置,然后通过这个位置取得了该位置上的数据。

image-20230726180541150

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/793179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

白话机器学习笔记(一)学习回归

最小二乘法 定义模型 表达式&#xff1a; f θ ( x ) θ 0 θ 1 x f_\theta(x)\theta_0\theta_1x fθ​(x)θ0​θ1​x &#xff08;常用 θ \theta θ表示未知数、 f θ ( x ) f_\theta(x) fθ​(x)表示含有参数 θ \theta θ并且和变量 x x x相关的函数&#xff09; 目标…

【每日一题】—— D. Prefix Permutation Sums (Codeforces Round 888 (Div. 3))

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;每日一题 &#x1f48c;其他专栏&#xff1a; &#x1f534; 每日反刍 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓称…

三自由度PUMA机器人非线性控制研究(Matlab代码、Simulink仿真实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码、Simulink仿真实现 &#x1f4a5;1 概述 针对三自由度PUMA560机器人的控制问题&#xff0c;可以使用三种不同的非线性控制算法&#xff1a;计算扭矩控制、滑模控制和反步…

RL 实践(5)—— 二维滚球环境【REINFORCE Actor-Critic】

本文介绍如何用 REINFORCE 和 Actor-Critic 这两个策略梯度方法解二维滚球问题参考&#xff1a;《动手学强化学习》完整代码下载&#xff1a;6_[Gym Custom] RollingBall (REINFORCE and Actor-Critic) 文章目录 1. 二维滚球环境2. 策略梯度方法2.1 策略学习目标2.2 策略梯度定…

石子合并(区间dp模板)

题目描述&#xff1a; dp分析&#xff1a; 解题代码&#xff1a; #include<iostream> using namespace std;const int N1e36;int f[N][N]; int a[N]; int s[N];int main(){int n;cin>>n;for(int i1;i<n;i){scanf("%d",&s[i]);s[i]s[i-1];//前缀和…

使用fastjson错误

说明&#xff1a;使用fastjson时&#xff0c;对象解析不成功&#xff0c;一直报错&#xff0c;但是json格式没有错&#xff1b; 错误信息&#xff1a;Method threw ‘com.alibaba.fastjson.JSONException’ exception. json数据是正确的 分析&#xff1a;注意看&#xff0c;fa…

【用IDEA基于Scala2.12.17开发Spark 3.4.1 项目】

目录 使用IDEA创建Spark项目设置sbt依赖创建Spark 项目结构新建Scala代码 使用IDEA创建Spark项目 打开IDEA后选址新建项目 选址sbt选项 配置JDK debug 解决方案 相关的依赖下载出问题多的话&#xff0c;可以关闭idea&#xff0c;重启再等等即可。 设置sbt依赖 将sbt…

数据安全问题防不胜防?教你使用铁威马的321原则

无论是勒索病毒的袭击&#xff0c;还是硬件损坏、人为误删等原因造成的数据丢失的意外让我们防不胜防。为此&#xff0c;我们时常建议大家尤其是企业通过【3-2-1备份原则】的数据保护策略来备份数据&#xff0c;以便在数据受损失时&#xff0c;能快速地从备份介质中完整地恢复数…

git相关

gerrit用户指南&#xff1a; 资料&#xff1a;Gerrit 用户指南 gerrit-user-guide 上述有介绍如何review&#xff0c;review并非修改代码之后如何重新提交等操作 jenkins介绍 Jenkins详细教程 - 知乎 一、jenkins是什么&#xff1f; Jenkins是一个开源的、提供友好操作界…

vite的介绍

Vite&#xff08;法语意为 "快速的"&#xff0c;发音 /vit/&#xff0c;发音同 "veet")是一种新型前端构建工具 优势 &#x1f4a1; 极速的服务启动&#xff0c;使用原生 ESM 文件&#xff0c;无需打包 ⚡️ 轻量快速的热重载&#xff0c;始终极快的模块…

Centos7.6安装RocketMQ4.9.2并配置开机自启

1、下载RocketMQ 编译后的压缩包 wget https://dlcdn.apache.org/rocketmq/4.9.2/rocketmq-all-4.9.2-bin-release.zip2、解压 unzip rocketmq-all-4.9.2-bin-release.zip3、进入解压文件夹 cd rocketmq-all-4.9.2/4、编辑配置文件/usr/local/rocketmq/rocketmq-all-4.9.4-…

Spring Boot 拦截器实现:登录验证 统一异常处理 返回数据规范化

学习 Spring 和 servlet 初期&#xff0c;我们在判断用户身份时&#xff0c;都是在每个方法中获取会话、获取对象&#xff0c;这种方式冗余度高&#xff0c;增加代码复杂度&#xff0c;维护成本也高&#xff0c;因此想到可以使用 AOP 来实现一个公共的方法&#xff0c;这个公共…

Android 自定义跳转到系统 Settings Fragment 的 Intent

以跳转到蓝牙控制面板为例&#xff0c;控制面板如图所示&#xff1a; 其 Fragment 所在的位置是&#xff1a; packages/apps/Settings/src/com/android/settings/connecteddevice/BluetoothDashboardFragment.java 第一步 要在 Settings的主要 Activity 中定义继承同一个父类…

通达信波段王指标公式_通达信公式

使用说明&#xff1a;1、买点&#xff1a;多空分界线变红后出现波段买为做多信号&#xff0c;中间出现波段卖信号为杂波可以不考虑&#xff0c;再结合逃顶信号进行卖出操作&#xff0c;如果没有出现逃顶信号&#xff0c;则可以等多空分界线变绿后结合波段卖信号综合做出判断。2…

基于proteus的纯模拟病房呼叫系统

摘要&#xff1a;无线的病房呼叫系统将病人的呼叫请求迅速传递给医护者&#xff0c;减少了信息传递的过程性&#xff0c;病人无需等待医护巡查才可求助&#xff0c;增加了便捷性与即时性&#xff1b;此外也减轻一定的工作量&#xff0c;加强服务的效率。本文基于proteus软件进行…

selenium 启动常用浏览器驱动方式

一.启动 Chrome 浏览器 方式一&#xff1a; // 驱动路径的 File File file new File("src/main/resources/drivers/chromedriver-win32.exe"); // 设置系统属性&#xff0c;setProperty() 中两个参数分别是驱动名和 file 绝对路径 System.setProperty("webdr…

如何在Mkdocs里自定义字体(霞鹜文楷)

网站目前在用的字体&#xff1a;霞鹜文楷 想必你可以直观的从我的网站&#xff0c;感受到这款字体的美观程度。 以下是摘录的部分字体官方介绍文档 注意事项 添字请在 Issue #33 反馈&#xff0c;字形调整请在 Issue #14 反馈&#xff0c;不要另开议题&#xff0c;以便于整理。…

SpringBoot——持久化技术

简单介绍 在之前我们使用的数据层持久化技术使用的是MyBatis或者是MyBatis-plus&#xff0c;其实都是一样的。在使用之前&#xff0c;我们要导入对应的坐标&#xff0c;然后配置MyBatis特有的配置&#xff0c;比如说Mapper接口&#xff0c;或者XML配置文件&#xff0c;那么除了…

为什么pmp证书只能对标cspm二级证书??

CSPM 认证是新出台的证书&#xff0c;9月才开始第一次考试&#xff0c;前期肯定不会太难的&#xff0c;而 CSPM 有五个等级&#xff0c;综合下来 PMP 对标的是PMP是CSPM-2 级&#xff0c;难度差不多&#xff0c;PgMP对标的是CSPM-3。 CSPM 能力等级划分为五个等级&#xff0c;从…

得物词分发平台技术架构建设与演进

前言 在文章开始前先介绍下导购&#xff0c;导购通常是指帮助消费者在购物过程中做出最佳决策的人或系统。在电商网站中&#xff0c;导购可以引导用户关注热卖商品或促销活动等&#xff0c;帮助用户更好地进行购物。导购的目的是为了提高用户的购物体验&#xff0c;促进销售额…