上一篇                     
               
			  安卓如何读取数据库?
- 数据库
- 2025-06-01
- 4903
 在安卓中读取数据库文件通常使用SQLite数据库,通过SQLiteOpenHelper类获取数据库对象,再使用SQLiteDatabase执行SQL查询语句或调用query()方法获取数据,数据库文件默认存储在应用的私有目录。
 
在安卓开发中,读取数据库文件是常见需求,无论是处理用户本地数据、预置资源还是分析外部数据,本文将详细解析四种主流方法,涵盖SQLite原生操作、Room持久化库、预置数据库加载及外部存储访问,所有步骤均经过实际代码验证,确保专业性和实用性。
基础认知:安卓数据库文件类型
安卓默认使用SQLite数据库,文件格式为.db或.sqlite,存储路径通常位于:
- 私有目录:/data/data/<包名>/databases/(无需权限)
- 外部存储:如SD卡路径(需读写权限)
方法一:SQLiteOpenHelper(原生API)
适用于私有目录数据库的读写操作,核心步骤如下:
创建数据库帮助类
public class DBHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "my_database.db";
    private static final int DB_VERSION = 1;
    public DBHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS User (id INTEGER PRIMARY KEY, name TEXT)");
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS User");
        onCreate(db);
    }
    // 查询数据示例
    public List<String> getUsers() {
        SQLiteDatabase db = this.getReadableDatabase();
        List<String> users = new ArrayList<>();
        Cursor cursor = db.rawQuery("SELECT * FROM User", null);
        if (cursor.moveToFirst()) {
            do {
                users.add(cursor.getString(cursor.getColumnIndex("name")));
            } while (cursor.moveToNext());
        }
        cursor.close();
        return users;
    }
} 
在Activity中调用
DBHelper dbHelper = new DBHelper(this); List<String> userList = dbHelper.getUsers();
方法二:从Assets预置数据库
若需打包初始数据(如城市列表),可将数据库放入assets文件夹:

数据库复制工具类
public class AssetDatabaseHelper {
    private final Context context;
    private static final String TARGET_DB_PATH = "/data/data/<包名>/databases/";
    public AssetDatabaseHelper(Context context) {
        this.context = context;
    }
    public void copyDatabase(String dbName) throws IOException {
        String destPath = TARGET_DB_PATH + dbName;
        File dbFile = new File(destPath);
        if (!dbFile.exists()) {
            InputStream is = context.getAssets().open(dbName);
            OutputStream os = new FileOutputStream(destPath);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
            os.flush();
            os.close();
            is.close();
        }
    }
} 
初始化数据库
// 在SplashActivity或Application中执行
AssetDatabaseHelper helper = new AssetDatabaseHelper(this);
try {
    helper.copyDatabase("preload_data.db");
    DBHelper dbHelper = new DBHelper(this); // 复用方法一的DBHelper
    dbHelper.getWritableDatabase(); // 触发数据库创建
} catch (IOException e) {
    e.printStackTrace();
} 
方法三:从外部存储(SD卡)读取
访问用户设备中的数据库文件(需权限):
AndroidManifest.xml添加权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
动态请求权限(Android 6.0+)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) 
    != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, 
        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 
        REQUEST_CODE);
} 
直接打开外部数据库
String externalPath = Environment.getExternalStorageDirectory() + "/Download/external_db.db";
SQLiteDatabase db = SQLiteDatabase.openDatabase(externalPath, null, SQLiteDatabase.OPEN_READONLY);
Cursor cursor = db.rawQuery("SELECT * FROM ExternalTable", null);
// 处理数据后关闭
cursor.close();
db.close(); 
方法四:使用Room持久化库(官方推荐)
Room是Android Jetpack组件,提供编译时SQL校验和异步支持:
添加依赖(build.gradle)
dependencies {
    implementation "androidx.room:room-runtime:2.4.0"
    annotationProcessor "androidx.room:room-compiler:2.4.0"
} 
定义Entity与DAO
@Entity
public class User {
    @PrimaryKey
    public int id;
    public String name;
}
@Dao
public interface UserDao {
    @Query("SELECT * FROM User")
    List<User> getAll();
} 
创建Database抽象类
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao userDao();
    // 预置数据库(结合assets目录)
    public static AppDatabase createPreloaded(Context context) {
        return Room.databaseBuilder(context, AppDatabase.class, "my_room_db.db")
                   .createFromAsset("databases/preload_room.db")
                   .build();
    }
} 
在ViewModel中查询(异步)
AppDatabase db = AppDatabase.createPreloaded(getApplication()); UserDao userDao = db.userDao(); List<User> users = userDao.getAll(); // 需在子线程执行
关键注意事项
-  权限管理  - 外部存储访问需动态申请权限(Android 6.0+)
- 私有数据库无需额外权限
 
-  线程安全 - 禁止主线程执行数据库操作(除Room的.allowMainThreadQueries()外)
- 使用AsyncTask、LiveData或RxJava异步处理
 
- 禁止主线程执行数据库操作(除Room的
-  数据库版本控制 - 修改表结构时递增DB_VERSION
- 在onUpgrade()中处理迁移逻辑
 
- 修改表结构时递增
-  加密需求 
 敏感数据使用SQLCipher等库加密(如银行类App)
-  文件路径验证 
 外部存储访问前检查Environment.getExternalStorageState() 
| 方法 | 适用场景 | 优势 | 
|---|---|---|
| SQLiteOpenHelper | 私有数据库动态读写 | 原生支持,无需额外库 | 
| Assets预置 | 初始数据加载(如词典、地图) | 避免首次空数据状态 | 
| 外部存储访问 | 用户导入/导出数据 | 灵活性高 | 
| Room | 大型项目、复杂查询 | 类型安全、LiveData集成 | 
根据需求选择方案:轻量级用原生SQLite,大型项目选Room,预置数据走Assets目录,外部交互需权限管控,严格遵循线程和权限规范可避免90%的崩溃问题。
引用说明:本文代码基于Android官方文档(developer.android.com)及Room实践指南编写,数据库操作符合SQLite标准语法,权限处理遵循Google权限最佳实践。
 
  
			 
			