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

一、文件的储存

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

React AntDesign写一个导出数据的提示语 上面有跳转的路径,或者点击知道了,关闭该弹层

效果如下&#xff1a; 代码如下&#xff1a; ForwardDataCenterModal(_blank);export const ForwardDataCenterModal (target?: string) > {let contentBefore React.createElement(span, null, 数据正在处理中&#xff0c;请稍后前往);let contentAfter React.creat…

JAVA基础-集合(List与Map)

目录 引言 一&#xff0c;Collection集合 1.1,List接口 1.1.1&#xff0c;ArrayList 1.1.1.1&#xff0c;ArrayList的add&#xff08;&#xff09;添加方法 1.1.1.2&#xff0c;ArrayList的remove&#xff08;&#xff09;删除方法 1.1.1.3&#xff0c;ArrayList的contai…

网络超时导致namenode被kill的定位

交换机升级导致部分网络通信超时, 集群的namenode主从切换后,主namenode进程被杀死。 网络问题导致namenode与zk间的连接超时触发了hadoop集群的防脑裂机制而主动kill掉了超时的namenode进程。 日志分析发现zk和namenode之间的网络连接超时: 超时触发了namenode切换,并将超时…

游戏引擎UE如何革新影视行业?创意云全面支持UE云渲染

虚幻引擎UE&#xff08;Unreal Engine&#xff09;作为一款“殿堂级”的游戏引擎&#xff0c;占据了全球80%的商用游戏引擎市场&#xff0c;但如果仅仅将其当做游戏开发的工具&#xff0c;显然是低估了它的能力。比如迪士尼出品的电视剧《曼达洛人》、电影《狮子王》等等都使用…

白话机器学习笔记(三)评估已建立的模型

模型评估 在进行回归和分类时&#xff0c;为了进行预测&#xff0c;我们定义了函数 f θ ( x ) f_\theta(x) fθ​(x)&#xff0c;然后根据训练数据求出了函数的参数 θ \theta θ。 如何预测函数 f θ ( x ) f_\theta(x) fθ​(x)的精度&#xff1f;看它能否很好的拟合训练数…

【Django学习】(十五)API接口文档平台_项目流程分析_日志器_认证_授权

一、API接口文档平台 使用API接口文档不经可以很好的的维护接口数据&#xff0c;还给测试人员的接口测试工作带来了便利&#xff1b; 我们可以在全局配置文件中添加路由路径生成接口文档 1、使用docs接口文档维护接口 1.1在全局配置文件里指定用于支持coreapi的Schema # 指…

Linux の shell 流程控制

条件控制 # if then 如果else 没有语句 可以省略 if condition then#语句 fi# if then 。。。 else 。。。 fi if condition then#语句 else#语句 fi# if condition then#语句 elif condition2 then#语句 else#语句 fiif [ $a -gt $b ] thenecho "a > b&quo…

骆驼祥子思维导图

《骆驼祥子》简单介绍 《骆驼祥子》小说&#xff0c;以20世纪20年代的旧北京为背景。祥子所处的时代是北洋军阀统治的时代。今天我们就用ProcessOn 思维导图 来给大家解析这本名著。所有文章中的思维导图都可以到ProcessOn 模板社区获得。 1936年&#xff0c;老舍的一位山东大…

[vulnhub]DC2

文章目录 [vulnhub]DC2信息收集flag1flag2cewlwpscan flag3什么是rbash&#xff1f; flag4flag5git提权 总结 [vulnhub]DC2 信息收集 扫ip&#xff0c;有两种方式&#xff1a;arp、nmap nmap -sP 192.168.56.0/24 -T4arp-scan -l192.168.56.137 扫端口&#xff1a; nmap -…

Mendix 创客访谈录|综合业务展示大屏应用开发

本期创客 刘书智 西门子工业领域专家 我在西门子工厂自动化工程有限公司工作。一直从事SCADA产品的技术支持工作&#xff0c;已经过去17个年头了。赶上数字化发展的浪潮&#xff0c;不断学习各种IT技术&#xff0c;践行 IT与OT融合&#xff0c;希望借助自己的IT知识助力OT的发…

力扣1114.按序打印-----题目解析

题目描述 解析&#xff1a; class Foo {public int a 0;public Foo() {}public void first(Runnable printFirst) throws InterruptedException {// printFirst.run() outputs "first". Do not change or remove this line.printFirst.run();a;}public void second…

vue全局状态管理工具 Pinia 的使用

先了解一下关于Pinia的一些故事&#xff0c;面试把这些讲给面试官挺加分的&#xff0c;同时这是我持续学习下去的动力 1.为什么叫Pinia&#xff1f; 官网解释是西班牙语中的 pineapple&#xff0c;即“菠萝”&#xff0c;菠萝花是一组各自独立的花朵&#xff0c;它们结合在一起…

【C语言】函数----详解

&#x1f341; 博客主页:江池俊的博客 &#x1f4ab;收录专栏&#xff1a;C语言——探索高效编程的基石 &#x1f4bb; 其他专栏&#xff1a;数据结构探索 &#x1f3e9;代码仓库&#xff1a;江池俊的代码仓库 &#x1f3aa; 社区&#xff1a;C/C之家社区(欢迎大家加入与我一起…

安装VMware

D:\VMware\VMware Workstation\ 输入许可证

Sentinel 规则持久化到 Nacos

一、Sentinel规则管理模式&#x1f349; Sentinel的控制台规则管理有三种模式&#xff1a; 原始模式&#x1f95d; 原始模式&#xff1a;控制台配置的规则直接推送到Sentinel客户端&#xff0c;也就是我们的应用。然后保存在内存中&#xff0c;服务重启则丢失 pull模式&#…

一文详解Spring Bean循环依赖

一、背景 有好几次线上发布老应用时&#xff0c;遭遇代码启动报错&#xff0c;具体错误如下&#xff1a; Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name xxxManageFacadeImpl: Bean with name xxxManageFa…

实验数据origin作图使用经验总结

使用Origin绘制实验数据图表时&#xff0c;可以遵循以下经验总结&#xff1a; 选择合适的图表类型&#xff1a; 根据实验数据的性质和目的&#xff0c;选择合适的图表类型&#xff0c;例如散点图、折线图、柱状图、饼图等。确保图表类型能够清晰地展示数据趋势和关系。 规范坐…

常用API学习08(Java)

格式化 格式化指的是将数据按照指定的规则转化为指定的形式 。 那么为什么需要格式化&#xff1f;格式化有什么用&#xff1f; 以数字类为例&#xff0c;假设有一个比分牌&#xff0c;在无人得分的时候我们希望以&#xff1a;“00&#xff1a;00”的形式存在&#xff0c;那么…

3.安装kubesphere

1.本地存储动态 PVC # 在所有节点安装 iSCSI 协议客户端&#xff08;OpenEBS 需要该协议提供存储支持&#xff09; yum install iscsi-initiator-utils -y # 设置开机启动 systemctl enable --now iscsid # 启动服务 systemctl start iscsid # 查看服务状态 systemctl status …

【C++修炼之路】继承

&#x1f451;作者主页&#xff1a;安 度 因 &#x1f3e0;学习社区&#xff1a;StackFrame &#x1f4d6;专栏链接&#xff1a;C修炼之路 文章目录 一、概念及定义二、基类和派生类对象赋值转换三、继承中的作用域四、派生类的默认成员函数五、继承与友元六、继承与静态成员七…