sqlite - 在 Flutter 中从文件中导入 Sqlite 数据库
问题描述
我有一个 Sqlite 数据库文件,它始终位于设备上的同一位置,位于名为 backup.db 的文档中。我想要的是导入该数据库以替换现有的 Sqlite 数据库,但我遇到了一些奇怪的错误。无论如何,这里是代码:
class DbHelper {
static const currentDatabaseVersion = 1;
Future<void> init() async {
Database db;
final dbPath = await ExtStorage.getExternalStoragePublicDirectory(
ExtStorage.DIRECTORY_DOCUMENTS);
final newPath = join(dbPath, '/backup.db');
String localDatabasePath = newPath;
//Internal database path
var databasesPath = await getDatabasesPath();
var path = join(databasesPath, "foodDB.db");
db = await openDatabase(path);
if (await db.getVersion() < currentDatabaseVersion) {
db.close();
await deleteDatabase(path);
await _checkParentDirectoryExists(path);
ByteData data = await _getByteDataFromLocalDatabase(localDatabasePath);
List<int> bytes = _databaseByteDataToList(data);
await _writeBytesToInternalDatabase(path, bytes);
db = await openDatabase(path);
db.setVersion(currentDatabaseVersion);
}
}
static Future<void> _checkParentDirectoryExists(var path) async {
try {
await Directory(dirname(path)).create(recursive: true);
} catch (e) {
print(e);
}
}
static Future<ByteData> _getByteDataFromLocalDatabase(
String localDatabasePath) async {
return await rootBundle.load(join(localDatabasePath));
}
static List<int> _databaseByteDataToList(ByteData data) {
return data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
}
static Future<void> _writeBytesToInternalDatabase(
var path, List<int> bytes) async {
await File(path).writeAsBytes(bytes, flush: true);
}
}
据我所知,它获取'documents'目录,将路径与Documents中已经存在的backup.db文件合并,然后如果它存在,它应该只导入它。让我知道我做错了什么。我正在使用ext_storage库来定位文档文件夹和sqlite当然能够导入数据库。
在另一个屏幕中,我这样调用这个函数:
DbHelper dbHelper = new DbHelper();
onTap: () => dbHelper.init(),
这是堆栈跟踪:
ter (25910): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: Unable to load asset: /backup.db
E/flutter (25910): #0 PlatformAssetBundle.load
package:flutter/…/services/asset_bundle.dart:225
E/flutter (25910): <asynchronous suspension>
E/flutter (25910): #1 DbHelper._getByteDataFromLocalDatabase
package:CWCFlutter/db/import_database.dart:72
E/flutter (25910): #2 DbHelper.init
package:CWCFlutter/db/import_database.dart:53
E/flutter (25910): <asynchronous suspension>
E/flutter (25910): #3 _FoodListState.build.<anonymous closure>
package:CWCFlutter/food_list.dart:919
E/flutter (25910): #4 GestureRecognizer.invokeCallback
package:flutter/…/gestures/recognizer.dart:183
E/flutter (25910): #5 TapGestureRecognizer.handleTapUp
package:flutter/…/gestures/tap.dart:598
E/flutter (25910): #6 BaseTapGestureRecognizer._checkUp
package:flutter/…/gestures/tap.dart:287
E/flutter (25910): #7 BaseTapGestureRecognizer.acceptGesture
package:flutter/…/gestures/tap.dart:259
E/flutter (25910): #8 GestureArenaManager.sweep
package:flutter/…/gestures/arena.dart:157
E/flutter (25910): #9 GestureBinding.handleEvent
package:flutter/…/gestures/binding.dart:362
E/flutter (25910): #10 GestureBinding.dispatchEvent
package:flutter/…/gestures/binding.dart:338
E/flutter (25910): #11 RendererBinding.dispatchEvent
package:flutter/…/rendering/binding.dart:267
E/flutter (25910): #12 GestureBinding._handlePointerEvent
package:flutter/…/gestures/binding.dart:295
E/flutter (25910): #13 GestureBinding._flushPointerEventQueue
package:flutter/…/gestures/binding.dart:240
E/flutter (25910): #14 GestureBinding._handlePointerDataPacket
package:flutter/…/gestures/binding.dart:213
E/flutter (25910): #15 _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (25910): #16 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (25910): #17 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (25910): #18 _invoke1 (dart:ui/hooks.dart:265:10)
E/flutter (25910): #19 _dispatchPointerDataPacket (dart:ui/hooks.dart:174:5)
当我点击按钮导入数据库时,它完全没有响应,不确定是什么问题。
解决方案
试试下面的代码。它与您想要的类似,但也具有版本控制系统。当您init
创建数据库时,它将在手机目录中打开数据库并检查其版本。如果它已过时或不存在,它将删除当前的并创建一个新的(或者在它不存在的情况下创建一个新的)。
static const currentDatabaseVersion = 1;
static Future<void> init() async {
Database db;
String localDatabasePath = 'your database path here';
//Internal database path
var databasesPath = await getDatabasesPath();
var path = join(databasesPath, "database.db");
db = await openDatabase(path);
if (await db.getVersion() < currentDatabaseVersion) {
db.close();
await deleteDatabase(path);
await _checkParentDirectoryExists(path);
ByteData data = await _getByteDataFromLocalDatabase(localDatabasePath);
List<int> bytes = _databaseByteDataToList(data);
await _writeBytesToInternalDatabase(path, bytes);
db = await openDatabase(path);
db.setVersion(currentDatabaseVersion);
}
}
static Future<void> _checkParentDirectoryExists(var path) async {
try {
await Directory(dirname(path)).create(recursive: true);
} catch (e) {
print(e);
}
}
static Future<ByteData> _getByteDataFromLocalDatabase(
String localDatabasePath) async {
return await rootBundle.load(join(localDatabasePath));
}
static List<int> _databaseByteDataToList(ByteData data) {
return data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
}
static Future<void> _writeBytesToInternalDatabase(
var path, List<int> bytes) async {
await File(path).writeAsBytes(bytes, flush: true);
}
推荐阅读
- pine-script - 只有在蜡烛关闭 5 分钟后才需要触发入场警报
- typescript - 如何解决“类型循环引用自身错误”?
- while-loop - Nim 中的迭代器生成函数:分配迭代器时工作,直接调用时卡住
- reactjs - React 测试模拟实现一,使用模拟函数
- javascript - Slick.js 循环问题
- java - 带有路径变量的 Spring Boot AuthenticationToken
- windows - Docker multistage - 如果基本图像不同,则参数不会持续存在
- javascript - 对象的类型未知
- java - 如何使用 RxJava 代替 AsyncTask 来加载数据?
- docker - Windows DockerFile 复制文件夹