Flutter文件存储插件file_storage的使用

发布于 1周前 作者 htzhanglong 来自 Flutter

Flutter文件存储插件file_storage的使用

这是一个简单的跨平台包,用于在特定平台的目标位置操作文件。在Web平台上使用idb_shim。

特性

  • 提供应用程序文件、文档和缓存文件的位置。
  • 在支持的目的地递归创建文件夹。
  • 检查某个路径是否存在。
  • 加载和保存二进制数据(List<int>)、文本(utf8编码)和JSON对象及数组。
  • 保存数据流(List<int>)。

使用

final fileStorage = FileStorage();
final documentsPath = await fileStorage.getDocumentsPath();
final filePath = '$documentsPath/my_folder/my_file.txt';
await fileStorage.ensurePathExists(filePath);
await fileStorage.saveText(filePath, 'My text');
final savedText = await fileStorage.loadText(filePath);
print('Saved text is: $savedText');

final bytes1 = Uint8List.fromList([1, 2, 3]);
final bytes2 = Uint8List.fromList([4, 5, 6]);
await fileStorage.saveStream(filePath, Stream.fromIterable([bytes1, bytes2]));

示例代码

import 'package:file_storage/file_storage.dart';
import 'package:flutter/material.dart';

void main()
{
  runApp(const MyApp());
}

class MyApp extends StatelessWidget
{
  const MyApp({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget
{
  final String title;

  const MyHomePage({super.key, required this.title});

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
{
  String get appFilesPath => _appFilesPath ?? '';
  String get docsFilesPath => _docsFilesPath ?? '';
  String get cacheFilesPath => _cacheFilesPath ?? '';
  String get destination => _destination ?? '';
  String get fileName => '$destination/${_fileNameController.text}';

  [@override](/user/override)
  void initState()
  {
    super.initState();
    _fileNameController = TextEditingController(text: 'my_files/my_text.txt');
    _textController = TextEditingController();
    _initPaths();
  }

  [@override](/user/override)
  void dispose()
  {
    _textController.dispose();
    _fileNameController.dispose();
    super.dispose();
  }

  [@override](/user/override)
  Widget build(final BuildContext context)
  {
    const pathNames = ['App files', 'Documents', 'Cache'];
    const padding = 8.0;
    final paths = [appFilesPath, docsFilesPath, cacheFilesPath];
    final tabSize = (MediaQuery.sizeOf(context).width - padding * 2) / paths.length - 1;
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: Padding(
        padding: const EdgeInsets.all(padding),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            InputDecorator(
              decoration: const InputDecoration(
                labelText: 'Destination:',
              ),
              child: ToggleButtons(
                isSelected: paths.map((p) => _destination == p).toList(),
                onPressed: (i) => setState(() => _destination = paths[i]),
                children: pathNames.map((n) => SizedBox(
                  width: tabSize.floorToDouble(),
                  child: Center(child: Text(n)),
                )).toList(),
              ),
            ),
            TextFormField(
              decoration: const InputDecoration(
                labelText: 'File name:',
              ),
              controller: _fileNameController,
              autovalidateMode: AutovalidateMode.always,
              validator: (value) => value == null || value.isEmpty
                ? 'Enter the file name'
                : null,
              onChanged: (_) => setState(() {}),
            ),
            TextFormField(
              decoration: const InputDecoration(
                labelText: 'Text in the file:',
                helperText: 'Press Load or change the text and press Save.'
              ),
              controller: _textController,
            ),
            const SizedBox(height: 8.0),
            ElevatedButton(
              onPressed: _load,
              child: const Text('Load'),
            ),
            const SizedBox(height: 8.0),
            ElevatedButton(
              onPressed: _fileNameController.text.isEmpty ? null : _save,
              child: const Text('Save'),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _initPaths() async
  {
    final appFilesPath = await _fileStorage.getFilesPath();
    setState(() => _appFilesPath = appFilesPath);
    final docsFilesPath = await _fileStorage.getDocumentsPath();
    setState(() => _docsFilesPath = docsFilesPath);
    final cacheFilesPath = await _fileStorage.getCachePath();
    setState(() => _cacheFilesPath = cacheFilesPath);
    setState(() => _destination = appFilesPath);
  }

  Future<void> _load() async
  {
    final text = await _fileStorage.loadText(fileName);
    _textController.text = text ?? '';
    if (mounted && text == null) {
      await showDialog(
        context: context,
        builder: (context) => AlertDialog(
          title: const Text('The file does not exist'),
          content: Text('File path: $fileName'),
          actions: [
            TextButton(
              onPressed: () => Navigator.of(context).pop(),
              child: const Text('Ok'),
            ),
          ],
        ),
      );
    }
  }

  Future<void> _save() async
  {
    await _fileStorage.ensurePathExists(fileName);
    await _fileStorage.saveText(fileName, _textController.text);
    if (!mounted) return;
    await showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Text is successfully saved'),
        content: Text('File path: $fileName'),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: const Text('Ok'),
          ),
        ],
      ),
    );
  }

  late TextEditingController _fileNameController;
  late TextEditingController _textController;

  String? _appFilesPath;
  String? _docsFilesPath;
  String? _cacheFilesPath;
  String? _destination;

  final _fileStorage = FileStorage();
}

更多关于Flutter文件存储插件file_storage的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter文件存储插件file_storage的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用file_storage插件进行文件存储的示例代码。需要注意的是,file_storage并非Flutter官方插件,且社区中流行的文件存储插件通常是path_providersqflite(用于数据库存储)。不过,为了符合你的要求,这里假设存在一个名为file_storage的插件,并提供一个类似的文件存储实现示例。如果你实际使用的是其他插件,请参考相应插件的文档。

首先,确保你的pubspec.yaml文件中已经添加了file_storage依赖(这里假设它存在,实际使用时请替换为正确的插件名,如path_provider):

dependencies:
  flutter:
    sdk: flutter
  file_storage: ^x.y.z  # 替换为实际版本号

然后,运行flutter pub get来获取依赖。

接下来是一个简单的Flutter应用示例,展示如何使用file_storage插件进行文件读写操作。请注意,以下代码是基于假设的file_storage插件接口编写的,实际使用时请参考具体插件的API文档。

import 'package:flutter/material.dart';
import 'package:file_storage/file_storage.dart'; // 假设的插件导入

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'File Storage Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: FileStorageDemo(),
    );
  }
}

class FileStorageDemo extends StatefulWidget {
  @override
  _FileStorageDemoState createState() => _FileStorageDemoState();
}

class _FileStorageDemoState extends State<FileStorageDemo> {
  String _readContent = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('File Storage Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            TextField(
              decoration: InputDecoration(labelText: 'Enter some text'),
              onChanged: (text) {
                // 当文本改变时,保存到文件
                _saveTextToFile(text);
              },
            ),
            SizedBox(height: 20),
            Text('Read from file:', style: TextStyle(fontSize: 18)),
            Text(_readContent, style: TextStyle(fontSize: 16)),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _readFileFromStorage,
        tooltip: 'Read File',
        child: Icon(Icons.file_download),
      ),
    );
  }

  Future<void> _saveTextToFile(String text) async {
    final FileStorage storage = FileStorage(); // 假设的插件实例化
    final String fileName = 'example.txt';
    final String dirPath = await storage.getApplicationDocumentsDirectory(); // 获取应用文档目录
    final String filePath = '$dirPath/$fileName';

    // 将文本写入文件
    await storage.writeFile(filePath, text);
  }

  Future<void> _readFileFromStorage() async {
    final FileStorage storage = FileStorage(); // 假设的插件实例化
    final String fileName = 'example.txt';
    final String dirPath = await storage.getApplicationDocumentsDirectory(); // 获取应用文档目录
    final String filePath = '$dirPath/$fileName';

    // 从文件读取文本
    String content = await storage.readFile(filePath);
    setState(() {
      _readContent = content;
    });
  }
}

注意

  1. 上面的代码是基于假设的file_storage插件API编写的。实际使用时,你需要根据具体插件的API文档进行调整。
  2. 常见的文件存储插件如path_provider用于获取文件系统路径,而sqflite用于数据库存储。如果你需要文件存储功能,建议查阅这些插件的文档。
  3. 对于path_provider插件,获取应用文档目录的代码如下:
import 'package:path_provider/path_provider.dart';

Future<String> getApplicationDocumentsDirectory() async {
  final directory = await getApplicationDocumentsDirectory();
  return directory.path;
}
  1. 对于文件读写操作,你可以使用Dart的File类,它位于dart:io库中。

希望这个示例能对你有所帮助!如果有任何进一步的问题,请随时提问。

回到顶部