【问题标题】:Sqlite in flutter, how database assets workFlutter中的Sqlite,数据库资产如何工作
【发布时间】:2018-07-17 14:38:41
【问题描述】:

我正在查看此 (https://github.com/tekartik/sqflite/blob/master/doc/opening_asset_db.md) 以填充已格式化且应用程序需要的数据,仅用于读取功能。

因此,当我们已经拥有外部 CSV 文件中的所有信息时,我对创建 SQLite 数据库的理解是,在我的应用程序的 .dart 文件中创建类模型,例如

class User {

  int id;
  String _firstName;
  String _lastName;
  String _dob;

  User(this._firstName, this._lastName, this._dob);

  User.map(dynamic obj) {
    this._firstName = obj["firstname"];
    this._lastName = obj["lastname"];
    this._dob = obj["dob"];
  }

  String get firstName => _firstName;

  String get lastName => _lastName;

  String get dob => _dob;

  Map<String, dynamic> toMap() {
    var map = new Map<String, dynamic>();
    map["firstname"] = _firstName;
    map["lastname"] = _lastName;
    map["dob"] = _dob;
    return map;
  }
  void setUserId(int id) {
    this.id = id;
  }
}

如果我有一个 CSV 文件,其中包含所有用户信息(其值对应于用户类),我是否可以使用数据库资产来填写信息,然后在其中调用它颤振应用程序?我意识到可能有很多方法可以解决这个问题,但是 .db 文件究竟存储的是什么,它的格式如何?我可以在这个 .db 文件中实现一个 .csv 文件吗?

【问题讨论】:

    标签: database sqlite flutter dart sqflite


    【解决方案1】:

    首先,您需要从 csv 构建一个 sqlite 数据库。这可以通过以下方式完成:

    1. 创建必要的表(users.sql)

      CREATE TABLE users(
         firstname TEXT NOT NULL,
         lastname TEXT NOT NULL,
         dob TEXT NOT NULL
      );
      
    2. 创建 sqlite 数据库

      sqlite3 database.db < users.sql
      
    3. 插入 csv 数据

      sqlite3 database.db
      .mode csv
      .import data.csv users
      
    4. 将 database.db 放入您的资产中并将其添加到 pubspec.yaml 中。

      flutter:
        # ...
        assets:
          - assets/database.db
      
    5. 在您的应用中,您必须将资产文件复制到“文档”中。这有点复杂。

      // Construct a file path to copy database to
      Directory documentsDirectory = await getApplicationDocumentsDirectory();
      String path = join(documentsDirectory.path, "asset_database.db");
      
      // Only copy if the database doesn't exist
      if (FileSystemEntity.typeSync(path) == FileSystemEntityType.notFound){
        // Load database from asset and copy
        ByteData data = await rootBundle.load(join('assets', 'database.db'));
        List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
      
        // Save copied asset to documents
        await new File(path).writeAsBytes(bytes);
      }
      
    6. 最后,您可以像这样访问数据库。

      Directory appDocDir = await getApplicationDocumentsDirectory();
      String databasePath = join(appDocDir.path, 'asset_database.db');
      this.db = await openDatabase(databasePath);
      initialized = true;
      
    7. 示例查询(this._initialize() 是第 6 步)

      Future<List<Page>> search(String word, int parentId) async {
          if (!initialized) await this._initialize();
          String query = '''
            SELECT * FROM users
            LIMIT 25''';
          return await this.db.rawQuery(query);
      }
      

    【讨论】:

    • 您可能需要将“.import data.csv”编辑为“.import data.csv users”。语法说它需要一个表
    • 我正在使用android studio,当我使用资产下的.db文件时,它说.db与任何文件类型都没有关联
    • 没错。文件扩展名不是必需的。您可以将 .db 更改为 .sqlite3 (我认为这很常见),或者您可以完全放弃它。这是一个非关键警告。您可以在 sqflite 自述文件中看到作者也使用“.db”。
    • 这是一个sqlite数据库文件。它是一个二进制文件。您收到一个错误,因为它没有以 utf-8 编码。如果您尝试在文本编辑器中打开它,您会看到许多奇怪的字符,因为编辑器正在尝试解码不应解码的内容。请按照我为您提供的步骤操作。您可以通过运行sqlite3 database.db 与您的数据库进行交互,这将为您提供一个 sqlite 提示。
    • 这个答案非常好。请注意,FileSystemEntityType.NOT_FOUND弃用。使用FileSystemEntityType.notFound
    【解决方案2】:

    这个 .db 文件用于保存 SQL 数据。因此您可以使用 SQL 命令保存和获取数据。插件本身会解析.db文件中的数据。

    如果您想将数据保存为 CSV 并在课堂上解析,最好将数据存储在原始文件中(查看here 以保存文件)或使用this plugin。 虽然,还有一些其他方法可以将数据保存为 JSON 文件或将其保存在 key-value pair 中。

    【讨论】:

    • 好的,我所做的是做一个 mysql 转储并将 .db 用作文档资产,我将如何查询该文件?不列出它,而是让它显示在终端中
    • R. C. Howell 的回答对于使用 SQL 和 CSV 文件是完整的。但我建议使用使用键值对的 JSON。如果您有兴趣使用它,请告诉我编辑我的答案并添加 JSON 方式。
    【解决方案3】:

    在项目根目录的文件系统中添加资产。创建一个 assets 文件夹并将您的 db 文件放入其中:

    assets/examples.db
    

    在颤振部分的 pubspec.yaml 中指定资产

    flutter:
    
      assets:
    
        - assets/example.db
    

    如果存在则需要打开数据库,不存在则复制。

    此处的链接显示了打开/复制预先存在的 sqlite 数据库的代码:

    https://github.com/tekartik/sqflite/blob/master/sqflite/doc/opening_asset_db.md

    【讨论】:

    • 是否可以更新该数据库?我使用相同的方法打开数据库,但是当我更新它时,没有发生错误,但数据没有改变......有什么想法吗?
    【解决方案4】:

    我使用此功能从资产文件夹复制数据库

    Future<void> _copyDatabase() async {
        final String databasePath = await getDatabasesPath();
        final String path = join(databasePath, 'dic.db');
        final File file = File(path);
        if (!file.existsSync()) {
          ByteData data = await rootBundle.load(join('assets', 'dic.db'));
          List<int> bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
          await file.writeAsBytes(bytes, flush: true);
          logger.i('database successfully copied to $path');
        } else {
          logger.i('database already exist');
        }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 2018-10-18
      • 1970-01-01
      相关资源
      最近更新 更多