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

一、文件的储存

1、将数据储存到文件中

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

MODE_PRIVATE:会覆盖源文件数据

MODE_APPEND:在源文件后追加数据

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

java 复制代码
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()方法,用于读取文件。只接收一个参数及要读取的文件名。

读取数据代码如下:

java 复制代码
    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()用于逐个读取字符的整数值,并需要自己处理字符的连接以获取完整的文本数据。这种方法更适合处理二进制数据或特殊的文本处理场景。

java 复制代码
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 实现代码

java 复制代码
@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();

}

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

3、从SharedPrefrences中读取数据

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

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

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

java 复制代码
@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));
        }
    });

}

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

三、SQLite

1、创建数据库

建立一个MyDatabase类继承SQLite

重写onCreate、onUPgrade方法

获得MyDatabase的实例

选择打开方式打开

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

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

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

  • getWritableDatabase方法将会出现异常

SQL建立表语句:

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是自动增长的。

java 复制代码
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中使用数据库

java 复制代码
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中直接加入建表语句是不行的。

java 复制代码
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 语句,用于删除表,使用这个语句时要小心,因为一旦执行,表中的所有数据将被永久删除,并且无法恢复。这通常用于在数据库中不再需要某个表时进行清理。

java 复制代码
@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基础请看下面这段代码,没有请自行忽略这个问题。

java 复制代码
    @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中添加数据,只需要将表中的每个列名以及相应的待添加数据传入即可。

java 复制代码
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);
    }
});

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

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

id integer primary key autoincrement

4、更新数据------updata

java 复制代码
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

java 复制代码
//删
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个参数

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

java 复制代码
//查
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());
        }
    }
});

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

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

相关推荐
zhangphil几秒前
Android基于Path的addRoundRect,Canvas剪切clipPath简洁的圆形图实现,Kotlin(2)
android·kotlin
木向2 分钟前
leetcode22:括号问题
开发语言·c++·leetcode
comli_cn3 分钟前
使用清华源安装python包
开发语言·python
筑基.9 分钟前
basic_ios及其衍生库(附 GCC libstdc++源代码)
开发语言·c++
Calvin88082821 分钟前
Android Studio 的革命性更新:Project Quartz 和 Gemini,开启 AI 开发新时代!
android·人工智能·android studio
m0_7482451723 分钟前
Web第一次作业
java
小码的头发丝、23 分钟前
Java进阶学习笔记|面向对象
java·笔记·学习
雨颜纸伞(hzs)24 分钟前
C语言介绍
c语言·开发语言·软件工程
J总裁的小芒果26 分钟前
THREE.js 入门(六) 纹理、uv坐标
开发语言·javascript·uv
m0_5485147727 分钟前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript