sqlite3.dart icon indicating copy to clipboard operation
sqlite3.dart copied to clipboard

How to read the bytes of a VirtualFileSystemFile?

Open jimmyff opened this issue 1 year ago • 1 comments

Hi, I'm trying to access the bytes of my sqlite database file. How do I do that on the web? xOpen and xRead are super confusing and I can't find an example.

Working none-web implementation



import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:path_provider/path_provider.dart';
import 'package:sqlite3/common.dart';
import 'package:sqlite3/sqlite3.dart';

Future<CommonDatabase> loadDb() async {
  final applicationDir = await getApplicationDocumentsDirectory();
  final file = File(applicationDir.path + '/foobar.db');
  return sqlite3.open(file.path);
}

Future<Uint8List> dbBytes() async {
  final applicationDir = await getApplicationDocumentsDirectory();
  final file = File(applicationDir.path + '/foobar.db');
  return file.readAsBytes();
}

Not working web implementation


import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'package:sqlite3/wasm.dart';

Future<CommonDatabase> loadDb() async {
  final sqlite = await WasmSqlite3.loadFromUrl(Uri.parse('sqlite3.wasm'));
  final fileSystem = await IndexedDbFileSystem.open(dbName: 'foobar');

  sqlite.registerVirtualFileSystem(fileSystem, makeDefault: true);
  return sqlite.open('foobar.db', mode: OpenMode.readWriteCreate);
}

Future<Uint8List> dbBytes() async {
  final fileSystem = await IndexedDbFileSystem.open(dbName: 'foobar');
  final open = fileSystem.xOpen(
      Sqlite3Filename('foobar.db'), SqlFlag.SQLITE_OPEN_READONLY);
  print(open.file);
  return (open.file as File).readAsBytes();
}

Thanks!

jimmyff avatar Nov 05 '24 14:11 jimmyff

There's a somewhat-related example here.

We're not using dart:io files on the web and instead mirror structures used by sqlite3 internally, which is also the reason the methods are named the way they are. So the way to go is to xOpen the file as you're doing it, and then call xRead with a Uint8List that you've allocated (you can use xFileSize() to get the current size) to read bytes from the file into a buffer. Then you just need to xClose() the file after you're done. I didn't test this, but I imagine something like this should work:

Future<Uint8List> dbBytes() async {
  final fileSystem = await IndexedDbFileSystem.open(dbName: 'foobar');
  final open = fileSystem.xOpen(
      Sqlite3Filename('foobar.db'), SqlFlag.SQLITE_OPEN_READONLY);
  final buffer = Uint8List(open.xFileSize());
  file.xRead(buffer, 0); // read from offset 0 (entire file)
  file.xClose();
  fileSystem.close();
}

simolus3 avatar Nov 06 '24 00:11 simolus3