Flutter dart导出配置单元已将保存的数据保存到文件中,以便稍后检索



我正在开发一个条形码应用程序,并将数据保存到hive中。我需要知道的是,有一种方法可以将保存的配置单元数据库导出到备份文件中,并能够在应用程序崩溃或手机丢失时进行检索。这是为盲人提供的。想要将数据导出到一个文件中,我可以将其保存到我的电脑中存储,如果发生了什么事情,我不必再次扫描所有产品来构建数据库。如果蜂箱不能做到这一点,有人能给我指明一个方向,让飞镖数据库做到这一步吗。谢谢

好的,答案对我不起作用。这是我的模型文件的副本

import 'package:hive/hive.dart';
part 'product.g.dart';
@HiveType(typeId: 0)
class Product extends HiveObject{
@HiveField(0)
String itemName;
@HiveField(1)
String barCode;
@HiveField(2)
String bcType;
Product(this.itemName, this.barCode, this.bcType);
}

然后我打电话给我的盒子var box=Hive.box("产品");

如何将其编码为json进行保存?

我使用下一个

Future<File> _createBackupFile() async {
/// This example uses the OS temp directory

File backupFile=文件('${Directory.systemTemp.path}/backup_barcode.json');

try {
/// barcodeBox is the [Box] object from the Hive package, usually exposed inside a [ValueListenableBuilder] or via [Hive.box()]
var barcodeBox = Hive.box<Product>('products');
backupFile = await backupFile.writeAsString(jsonEncode(barcodeBox.values));
return backupFile;
} catch (e) {
// TODO: handle exception
print(e);
}
}

;开箱即用";据我所知,这是一个解决方案。这在很大程度上取决于你想要如何做到这一点的用例(因为有很多方法)。关于我如何为我的应用程序做到这一点的完整示例,您可以在这里查看:https://github.com/Kounex/obs_blad/blob/master/lib/views/settings/logs/log_detail/log_detail.dart(我使用共享包是为了方便导出,但这不是必要的)

Flutter也有自己的读写文件文档(https://Flutter.dev/docs/cookbook/persistence/reading-writeting-files)-我将添加一些信息来汇总:

存储位置


首先,我们必须考虑将";备份文件";。Flutter自己公开了公共路径,您可以使用这些路径(此外,path_provider包还为您提供了更大的灵活性)。如果你希望这个备份文件是临时的,你可以使用例如:

Directory.systemTemp;

该文档指出:"这是由操作系统提供的用于在中创建临时文件和目录的目录操作系统会确保在不同的场合删除它们,这样你就不必担心了。你也可以在这个临时目录中创建额外的目录,使其更容易区分,比如:

Directory.systemTemp.createTemp('my_app');

重要信息:这适用于非敏感数据。如果您正在处理的内容包含敏感数据(如姓名、地址等),则必须确保数据安全/数据隐私。在这种情况下,我会使用前面提到的path_provider包,在documents目录(getApplicationDocumentsDirectory())中创建这些文件,并确保在使用/导出后立即删除它们。即使加密内容也可能是个好主意,但我不会在这里深究。

文件管理


一旦我们知道在哪里存储文件,我们只需要创建它们。前面的flutter文档的第3章和第4章准确地说明了如何做到这一点,所以我更关注要写什么

编写数据的一种常见且非常方便的方法是JSON。Flutter也有相关文档:https://Flutter.dev/docs/development/data-and-backend/json

由于您正在使用Hive,您可能已经有代表框中条目的类,您可以很容易地添加toJson()函数,在其中返回Map<String, dynamic>(如文档中所示),然后您可以使用它将所需信息最终写入文件。

基于您的Hive类,以下是如何在otder中对其进行调整以正确序列化:

import 'package:hive/hive.dart';
part 'product.g.dart';
@HiveType(typeId: 0)
class Product extends HiveObject{
@HiveField(0)
String itemName;
@HiveField(1)
String barCode;
@HiveField(2)
String bcType;
Product(this.itemName, this.barCode, this.bcType);
/// This function will automatically be used by the [jsonEncode()] function internally
Map<String, dynamic> toJson() => {
'itemName': this.itemName,
'barCode': this.barCode,
'bcType': this.bcType,
}
}

一个小示例实现可能如下所示:

Future<File?> _createBackupFile() async {
/// This example uses the OS temp directory
File backupFile = File('${Directory.systemTemp.path}/backup_barcode.json');
try {
/// barcodeBox is the [Box] object from the Hive package, usually exposed inside a [ValueListenableBuilder] or via [Hive.box()]
backupFile = await backupFile.writeAsString(jsonEncode(barcodeBox.values));
return backupFile;
} catch (e) {
// TODO: handle exception
}
}

这将把配置单元框的JSON表示保存在临时操作系统目录中。你可以用最适合你的东西交换目录(例如在安卓系统上,在外部存储上,更容易访问)。

现在你必须考虑如何以及何时触发这个。您可以通过触发按钮手动执行此操作,例如,也可以在某个操作(如添加新条形码)后自动执行,然后选择适合您访问文件的方式。如前所述,将文件保存在易于访问的地方,如Android上的外部存储或使用共享包是可能的解决方案。

Android清单应该包含以下内容:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:requestLegacyExternalStorage="true"

您需要此程序包和此程序包才能继续。

现在有一种将数据备份到所需位置的方法:

Future<void> createBackup() async {
if (Hive.box<Product>('products').isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('No Products Stored.')),
);
return;
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Creating backup...')),
);
Map<String, dynamic> map = Hive.box<Product>('products')
.toMap()
.map((key, value) => MapEntry(key.toString(), value));
String json = jsonEncode(map);
await Permission.storage.request();
Directory dir = await _getDirectory();
String formattedDate = DateTime.now()
.toString()
.replaceAll('.', '-')
.replaceAll(' ', '-')
.replaceAll(':', '-');
String path = '${dir.path}$formattedDate.json';//Change .json to your desired file format(like .barbackup or .hive).
File backupFile = File(path);
await backupFile.writeAsString(json);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Backup saved in folder Barcodes')),
);}

Future<Directory> _getDirectory() async {
const String pathExt = 'Barcodes/';//This is the name of the folder where the backup is stored
Directory newDirectory = Directory('/storage/emulated/0/' + pathExt);//Change this to any desired location where the folder will be created
if (await newDirectory.exists() == false) {
return newDirectory.create(recursive: true);
}
return newDirectory;
}

最后,使用按钮调用此函数,它将以JSON格式保存一个以当前时间为名称的备份。

createBackup()

之后将数据恢复回Hive,

Future<void> restoreBackup() async {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Restoring backup...')),
);
FilePickerResult? file = await FilePicker.platform.pickFiles(
type: FileType.any,
);
if (file != null) {
File files = File(file.files.single.path.toString());
Hive.box<Product>('products').clear();
Map<String, dynamic> map = jsonDecode(await files.readAsString());
for (var i = 0; i < map.length; i++) {
Product product = Product.fromJson(i.toString(), map);
Hive.box<Product>('products').add(product);
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Restored Successfully...')),
);
}
}

最后,使用按钮调用此函数,它将打开文件选择器,您可以在其中选择备份文件,它将删除现有数据并循环添加备份中的每一项。

restoreBackup()

最新更新