上一篇
在安卓中读取数据库文件通常使用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权限最佳实践。
