首页 > 其他分享 >33.Android数据存储

33.Android数据存储

时间:2024-04-20 10:55:42浏览次数:17  
标签:Toast 存储 33 et import Android btn id android

数据存储方式:
对比sql数据库呗


1.文件存储
方式同java中I/O输入输出流一样

举个例子:

public class 字节流_写文本文件 {
    public static void main(String[] args) throws IOException {
        /**字节流创建文本文件。在D盘SS目录中创建students.txt文件,并添加以下信息:
         * 姓名:张三,性别:男,年龄:19,成绩:90,入学日期:2022-9-10
         * 姓名:李四,性别:女,年龄:19,成绩:95,入学日期:2022-9-9
         */
        String str="姓名:张三,性别:男,年龄:19,成绩:90,入学日期:2022-9-10 " +
                "姓名:李四,性别:女,年龄:19,成绩:95,入学日期:2022-9-9";
            OutputStream fileOutputStream = new FileOutputStream("D:\\SS\\students.txt");
            //OutputStream是所有输出流的父类,为一个抽象类
        byte[] bytes = str.getBytes();    // getBytes()将字符串转换为字节数组
        for (int i = 0; i < bytes.length; i++) {
            fileOutputStream.write(bytes[i]);
        }
            fileOutputStream.close();   //关闭输出流并释放与其关联的所有系统资源
    }
}

public class 字节流_读文本文件 {
    public static void main(String[] args) throws IOException {
        InputStream fileInputStream = new FileInputStream("D:\\SS\\students.txt");
        byte[] bytes =new byte[170];
        int b;
        while ((b=fileInputStream.read(bytes))!=1){
            System.out.println(new String(bytes,0,b));
            //将指定byte数组中从起始索引off开始的len字节写入输出流
            //      b={'1' ,'2', '3', '4', '5', '6', '7', '8'};
            //      String item=new String(b,2,2)
            //      结果 item=34
        }
        fileInputStream.close();

    }
}

来看看Android中的:
首先分为内部存储和外部存储
:外部存储就是SD卡之类的 属于永久性的存储方式 但不安全

三项:
获取SD卡的状态
判断是否可用
获取SD卡路径
        String state = Environment.getExternalStorageState();
        state.equals(Environment.MEDIA_MOUNTED);
        Environment.getExternalStorageDirectory();
然后再通过输入输出流写入读取就行
注意注意:申请SD卡写读文件的权限 要在清单文件中静态申请权限
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

主要来看看内部存储:
通过一个案例模拟qq登录:
image
image
layout布局就不写了

我没写trycatch这样是不对的 没有处理异常
但主要是为了验证
package com.example.store;

import android.content.Context;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

//工具类 实现QQ的账号密码存储和读取
public class Tool_qqAcitivity {
    public static boolean saveUser(Context context, String user, String pwd) throws IOException {
        FileOutputStream fos = context.openFileOutput("haha.txt", Context.MODE_PRIVATE);
        //将数据转换为字节码的形式写入haha.txt中
        fos.write((user + ":" + pwd).getBytes());
        fos.close();
        return true;

    }

    public static Map<String, String> getUser(Context context) throws IOException {
        String str = "";
        FileInputStream fis = context.openFileInput("haha.txt");
        byte[] buffer = new byte[fis.available()];
        fis.read(buffer);
        str = new String(buffer);
        HashMap<String, String> map = new HashMap<String, String>();
        String[] split = str.split(":");
        if (split.length >= 2) {
            map.put("user", split[0]);
            map.put("pwd", split[1]);
        } else {
            // 处理错误情况,例如文件内容格式不正确或为空
            // 可以选择抛出异常、记录日志或返回null等
            // 这里只是简单地返回一个空的map
            return new HashMap<>();
        }
        fis.close();
        return map;

    }

}

package com.example.store;

import android.os.Bundle;
import android.os.Environment;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import java.io.IOException;
import java.util.Map;

public class QQ_Activity extends AppCompatActivity {
    //初始化
    private EditText et_account;
    private EditText et_password;
    private Button btn_login;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_qq);
        et_account = findViewById(R.id.et_account);
        et_password = findViewById(R.id.et_password);
        btn_login = findViewById(R.id.btn_login);
        try {
            Map<String, String> user = Tool_qqAcitivity.getUser(this);
            if(user!=null){
                et_account.setText(user.get("user"));
                et_password.setText(user.get("pwd"));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }


        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String user = et_account.getText().toString().trim();
                String pwd = et_password.getText().toString();
                //检查是否为空
                if(TextUtils.isEmpty(user)){
                    Toast.makeText(QQ_Activity.this, "请输入账号", Toast.LENGTH_SHORT).show();
                    return;
                }
                if(TextUtils.isEmpty(pwd)){
                    Toast.makeText(QQ_Activity.this, "请输入密码", Toast.LENGTH_SHORT).show();
                    return;
                }
                Toast.makeText(QQ_Activity.this, "登录成功", Toast.LENGTH_SHORT).show();

                //保存用户信息 调用工具
                try {
                    boolean b = Tool_qqAcitivity.saveUser(QQ_Activity.this, user, pwd);
                    if(b){
                        Toast.makeText(QQ_Activity.this, "保存成功", Toast.LENGTH_SHORT).show();
                    }else {
                        Toast.makeText(QQ_Activity.this, "保存失败", Toast.LENGTH_SHORT).show();
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }

            }
        });
    }

}

需要注意的就是:
内部存储 当创建的应用程序被卸载时 内部存储文件也随之删除
权限参数:
MODE_PRIVATE 只能被当前程序读写
MODE_APPEND 内容可以追加
MODE_WORLD_READABLE 内容可被其他程序读
MODE_WORLD_WRITEABLE 内容可被其他程序写


2.SharedPreferences存储
一个轻量级存储类

       获取实例对象
        SharedPreferences 名字 = getSharedPreferences("名字", MODE_PRIVATE);
		获取编辑器
		通过键值对形式储存(put方法)在data/data/包名/shared_prefs中的XML中
        SharedPreferences.Editor edit = 名字.edit();
        edit.putString("key","value");
        edit.commit();
        读取数据
        名字.getString("key","不存在返回这个");
		移除数据
        edit.remove("key");
        edit.clear();

3.SQLite数据库存储
这个就有意思了 是Android自带的一个小型数据库
储存的文件在这里:
参考:https://blog.csdn.net/hjjshua/article/details/124150812
image
直接通过例子来看:

还是跳过layout布局文件

package com.example.store;

import android.annotation.SuppressLint;
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.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import org.w3c.dom.Text;


//在Activity中编写 与前面传递过来的属性 进行操作
public class SimpleDataActivity extends AppCompatActivity implements View.OnClickListener {
    //数据初始化
    MyHelper helper;
    private EditText et_id;
    private EditText et_name;
    private EditText et_age;
    private Button btn_add;
    private Button btn_query;
    private Button btn_update;
    private Button btn_delete;
    //用来展示结果
    private TextView tv_show;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);
        //调用自己继承SQLiteOpenHelper的MyHelper
        helper = new MyHelper(this);
        et_id = findViewById(R.id.et_id);
        et_name = findViewById(R.id.et_name);
        et_age = findViewById(R.id.et_age);
        btn_add = findViewById(R.id.btn_add);
        btn_query = findViewById(R.id.btn_query);
        btn_update = findViewById(R.id.btn_update);
        btn_delete = findViewById(R.id.btn_delete);
        tv_show = findViewById(R.id.tv_show);
        //第三种方法别忘记写这个
        btn_add.setOnClickListener(this);
        btn_query.setOnClickListener(this);
        btn_update.setOnClickListener(this);
        btn_delete.setOnClickListener(this);
    }

    //使用第三种方法继承接口实现方法 按钮点击后的改变 增删改查也在这里实现
    /*
        ContentValues类 它负责存储一些名值对
       它存储的名值对当中的名是一个String类型 而值都是基本类型
    */
    @Override
    public void onClick(View v) {
        String id, name, age;
        SQLiteDatabase db;
        ContentValues values;
        //Google写好的增删改查api
        if (v.getId() == R.id.btn_add) {
            //增
            //获取输入框的值
            id = et_id.getText().toString();
            name = et_name.getText().toString();
            age = et_age.getText().toString();
            //获取可读写的SQLiteDatabase对象
            db = helper.getWritableDatabase();
            //创建ContentValues对象
            values = new ContentValues();
            values.put("id", id);
            values.put("name", name);
            values.put("age", age);
            //三个参数  1.数据表名字 2.如果发现将要插入的行为空行 列名设为null 3.ContentValues对象
            db.insert("gao", null, values);
            Toast.makeText(this, "信息也添加", Toast.LENGTH_SHORT).show();
            //当使用完SQLiteDatabase对象后调用close方法关闭数据库连接 否则数据库一直存在 消耗内存
            db.close();
        }

        //查
        if (v.getId() == R.id.btn_query) {
            //获取可读的SQLiteDatabase对象
            db = helper.getReadableDatabase();
            //Cursor是一个游标接口 提供了便利查询结果的方法
            Cursor cursor = db.query("gao", null, null, null, null, null, null);
            //判断下是否有数据
            //两种Cursor对象的遍历方法

            //第一种先输出第一个值 再移动游标
            if (cursor.getCount() == 0) {
                Toast.makeText(this, "无数据", Toast.LENGTH_SHORT).show();
            } else {
                cursor.moveToNext();
                tv_show.append("id:" + cursor.getString(0) + " name:" + cursor.getString(1) + " age" + cursor.getString(2));
            }
            while (cursor.moveToNext()) {
                tv_show.append("\n" + "id:" + cursor.getString(0) + " name:" + cursor.getString(1) + " age" + cursor.getString(2));
            }
            //第二种先移动游标 再输出第一个值
//            if(cursor.getCount()>0){
//                while (cursor.moveToNext()) {
//                tv_show.append("id:" + cursor.getString(0) + " name:" + cursor.getString(1) + " age" + cursor.getString(2));
//            }
//            }else {
//                Toast.makeText(this, "无数据", Toast.LENGTH_SHORT).show();
//            }


            //用完Cursor 要关闭 否则造成内存泄漏
            cursor.close();
            db.close();
        }

        //修
        if (v.getId() == R.id.btn_update) {
            db = helper.getWritableDatabase();
            values = new ContentValues();
            values.put("name",name=et_name.getText().toString());
            values.put("age",name=et_age.getText().toString());
            // 数据表名字 最新数据 要修改数据的查找条件 查找条件的参数
            db.update("gao",values,"id=?",new String[]{
                    et_id.getText().toString()
            });
            Toast.makeText(this,"信息已修改",Toast.LENGTH_SHORT).show();
            db.close();
        }

        //删
        if (v.getId() == R.id.btn_delete) {
            db = helper.getWritableDatabase();
            db.delete("gao",null,null);
            Toast.makeText(this,"信息已删除",Toast.LENGTH_SHORT).show();
            db.close();
        }


    }

    //数据库和表的创建
    class MyHelper extends SQLiteOpenHelper {
        public MyHelper(Context context) {
            //四个参数  上下文 数据库名字 游标工厂 数据库版本
            super(context, "gao.db", null, 2);
        }

        // 创建表
        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL("create table gao(id int primary key,name varchar,age int)");
        }

        //数据库版本号增加时调用
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
    }


}

总结一下这个:
大致里面写的注释也够清楚了
其中两种Cursor对象的遍历方法
参考 https://blog.csdn.net/qq_64628470/article/details/129974041

当然还有其他数据存储方式
也对应着Android四大组件之一的内容提供者和观察者

标签:Toast,存储,33,et,import,Android,btn,id,android
From: https://www.cnblogs.com/gaodiyuanjin/p/18147323

相关文章

  • φ(* ̄0 ̄)3337. poj1845 sumdiv题解
    遇到数论题就要推式子!提供最美丽的latex\[a^b=p_1^{a_1*b}*p_2^{a_2*b}*p_3^{a_3*b}......*p_n^{a_n*b}\\那么他的因数之和为:\\({p_1}^0+{p_1}^1+...+{p_1}^{a_1*b})\\*({p_2}^0+{p_2}^1+...+{p_2}^{a_2*b})\\...\\*({p_n}^0+{p_n}^1+...+{p_n}^{a_n*b})\\=>利用等......
  • MySQL-05.存储引擎
    C-05.存储引擎为了方便管理,把连接管理,查询缓存,语法解析,查询优化这些不涉及真实数据存储的功能划分为MySQLServer的功能,把真实存取数据的功能划分为存储引擎的功能。所以在MySQLServer完成了查询优化后,只需按照生成的执行计划调用底层存储引擎提供的API,获取到数据后返回给客户端......
  • JZ33 二叉排序树的后序遍历序列
    classSolution{public://判断该数组是不是某二叉搜索树的后序遍历的结果。//如果是则返回true,否则返回false//注意传入参数是一个int类型的vector容器boolVerifySquenceOfBST(vector<int>sequence){if(sequence.empty()) //二叉树......
  • android studio jdk问题
    报错使用Terminal运行命令,报错:FAILURE:Buildfailedwithanexception.*Whatwentwrong:Aproblemoccurredconfiguringrootproject'StringFog'.>Couldnotresolveallfilesforconfiguration':classpath'.>Couldnotresolvec......
  • 段页式存储地址计算
    什么是段页式存储?在计算机系统中,存储器被分为很多个小块,每个小块被称为一页。而段页式存储是一种将存储器分为若干个段和页的存储管理方式。在这种方式下,每个进程都被分配了一个独立的地址空间,其中每个地址都由一个段号和一个页号组成。段页式存储地址计算在段页式存储中,地址的......
  • 珠宝黄金秤芯片方案sic8833
    珠宝黄金秤方案是由传感器和ADC芯片以及MCU等芯片组成,方案的设计需要多类元器件功能的配合才能够保证珠宝黄金秤方案能够实现我们所设想的功能。称重测量压力传感器是不能缺少的,而将模拟信号转换为数字信息ADC芯片又是不可或缺的,但要保证它们之前能够执行各自的功能区,MCU才是......
  • (学习)godot4.2 Android调试
      1勾选远程部署  2安装Android构建模板  3cmd运行以下命令获取debug.keystorekeytool-keyalgRSA-genkeypair-aliasandroiddebugkey-keypassandroid-keystoredebug.keystore-storepassandroid-dname"CN=AndroidDebug,O=Android,C=US"-valid......
  • 洛谷 p3372 线段树
    更改了线段树实现的方式,将lazy值作为单独的节点存在,降低存储压力structNode{longlongsum;Node():sum(0ll){}Nodeoperator+(constNode&other){Noderes=*this;res.sum+=other.sum;returnres;};voidapplyLazy(......
  • Android中使用系统的签名打包
    背景正常开发一个Android软件项目,我们会生成一个签名文件,具体实现方式详见:项目签名当我们开发一个系统级的app时,若apk已经集成到系统中,再想重新安装新包测试时一般会安装不上,提示签名不一致,原因是系统在整体编译时需要整体的来进行系统签名,当我们把新的apk往系统安装时,就会提示......
  • JavaScript本地存储的方式有哪些
    Web存储技术1.localStorage特点:长期存储,除非手动删除否则会一直保存在浏览器中,清除缓存或卸载浏览器后消失。存储语法:window.localStorage.setItem(名字,值)获取语法:window.localStorage.getItem(名字)删除语法:window.localStorage.removeItem(名字)作用:删除localStorage......