SQLite姓氏数据库首字母检索开发

具体讲解看博主的另一篇文章。

基于Android的SQLite姓氏数据库构建与首字母检索模块开发实战(最少代码量)-CSDN博客https://blog.csdn.net/weixin_72689660/article/details/160410622?sharetype=blogdetail&sharerId=160410622&sharerefer=PC&sharesource=weixin_72689660&spm=1011.2480.3001.8118

java 复制代码
package com.mySQLiteTest.SQLiteTest;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * @File Name: mySurnameDatabase .java
 * @Date: April 22, 2026
 * @Version: 1.0
 * @Author: 施棠海
 * @描述: 数据库安全初始化、安全获取数据。
 */

public class mySurnameDatabase {
    private static final String TAG = "mySurnameDatabase";

    private static final String DB_NAME    = "SurnameInitialDb.db"  ;   // 数据库名
    private static final String TABLE_NAME = "HundredFamilySurnames";   // 表名

    private static mySurnameDatabase instance;

    private Context mContext;
    private SQLiteDatabase database;

    private String dbPath;

    private boolean initialized = false;

    public mySurnameDatabase(Context context){
        mContext = context.getApplicationContext();
        // 获取数据库文件路径(指的是如果db文件拷贝,设备会默认放在哪个路径下,不需要这个文件当前真的在这个目录下存在)
        dbPath = mContext.getDatabasePath(DB_NAME).getAbsolutePath();
    }

    public static synchronized mySurnameDatabase getInstance(Context context){
        if (instance == null){
            // 第一次创建单例时调用构造函数
            instance = new mySurnameDatabase(context);
        }
        return instance;
    }

    public void initDB() {
        try {
            File dbFile = new File(dbPath);
            // 开始拷贝文件
            File dbFilePath = dbFile.getParentFile();
            if (!dbFilePath.exists()){  // 如果父目录不存在就递归创建所有父目录
                dbFilePath.mkdirs();
            }
            // 如果数据库文件已经存在,则删除
            if (dbFile.exists()){
                dbFile.delete();
            }

            // 创建数据库文件
            // InputStream 打开一条读取管道,程序可以从中一个字节一个字节地取数据
            // FileOutputStream 打开一条写入管道,程序通过它创建/覆盖文件并写入字节。创建一个文件输出流,向指定的文件写入数据。
            try (InputStream input = mContext.getAssets().open(DB_NAME);FileOutputStream output = new FileOutputStream(dbFile)){
                // 获取数据库文件大小
                int dbAvailable = input.available();
                Debug.i(TAG,"已发现数据库文件,大小:"+dbAvailable+" bytes");
                if (dbAvailable<=0){
                    // 发送错误信息
                    throw new IOException(DB_NAME+" 文件为空或不存在");
                }
                // 缓冲区buffer,用于存储数据库文件
                byte[] buffer = new byte[1024];
                int byteSizeAll = 0;
                int byteSize = 0;
                // 读取数据库文件
                // input.read(byte[] b)方法返回读取的字节数,如果返回0,则说明文件读取完毕。读取时会把读取的文件内容缓存到buffer中
                while ((byteSize = input.read(buffer)) > 0){
                    // 向指定的目录下写入指定的文件
                    output.write(buffer,0,byteSize);
                    byteSizeAll += byteSize;
                }
                // 刷新缓冲区,确保数据写入。刷新此输出流并强制将任何缓冲的输出字节写出
                output.flush();
                Debug.i(TAG,DB_NAME+" 文件复制完成。大小: "+byteSizeAll+" bytes。 路径: "+dbPath);
            }

            // 打开数据库并设置只读模式
            database = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY);
            initialized = true;
            Debug.i(TAG,"数据库初始化完成");
        } catch (IOException e) {
            Debug.e(TAG,"数据库初始化失败 "+ e.getMessage(),e);
            initialized = false;
        }
    }

    public String getInitial(String Surname){
        try {
            // 若未初始化,则初始化
            if(!initialized && database == null){
                Debug.i(TAG,"未初始化,执行初始化程序");
                initDB();
            }
            // 若初始化失败,则返回空值
            if(!initialized && database == null){
                Debug.i(TAG,"初始化失败,返回空值");
                return "";
            }
            // 若数据库未打开,则打开数据库
            if(!database.isOpen()){
                database = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY);
            }

            // 查询数据库并获取结果集
            Cursor cursor = database.rawQuery(
                    // SELECT 字段 FROM 表名 WHERE 条件
                    "SELECT Initial FROM " + TABLE_NAME + " WHERE Name = ?",
                    // 把参数放入数组中,SQLite会自动将问号替换为参数,防止SQL注入攻击。
                    new String[]{Surname}
            );
            String initial = null;
            // 使光标移到结果集的第一行,若当前行存在结果则返回 true,否则返回 false
            if(cursor.moveToFirst()){
                // 获取当前行指定列的值
                initial = cursor.getString(cursor.getColumnIndexOrThrow("Initial"));
            }
            // 关闭结果集,否则会内存泄露。
            cursor.close();
            Debug.i(TAG,"找到的首字母为 "+initial);
            return initial == null?"":initial;
        } catch (Exception e) {
            Debug.e(TAG,"获取首字母失败 "+e.getMessage(),e);
            return "";
        }
    }

    public void close(){
        try {
            if (database != null && database.isOpen()) {
                // 关闭数据库
                database.close();
            }
            database = null;
            instance = null;
            initialized = false;
            Debug.i(TAG,"成功关闭数据库");
        } catch (Exception e) {
            Debug.e(TAG,"关闭数据库异常 "+e.getMessage(),e);
        }
    }

}
相关推荐
weixin_408717772 小时前
mysql如何查询所有列_mysql select星号性能分析
jvm·数据库·python
a9511416422 小时前
mysql权限表查询性能如何优化_MySQL系统权限缓存原理
jvm·数据库·python
zxrhhm2 小时前
Oracle RAC 日常监控脚本
数据库·oracle
m0_748920362 小时前
Redis怎样防止主从节点淘汰行为不一致
jvm·数据库·python
misL NITL2 小时前
数据库操作与数据管理——Rust 与 SQLite 的集成
数据库·rust·sqlite
2401_835956812 小时前
SQL中如何查找特定的空值行:WHERE IS NULL深度解析
jvm·数据库·python
若兰幽竹2 小时前
【从零开始编写数据库系统:架构设计与实现】第3章 SQL解析:词法与语法分析
数据库·sql·教学数据库·数据库内核开发
geBR OTTE2 小时前
开源的Text-to-SQL工具WrenAI
数据库·sql·开源
梦梦代码精2 小时前
LikeShop 深度测评:开源电商的务实之选
java·前端·数据库·后端·云原生·小程序·php