讀取和寫入檔案
在某些情況下,您需要讀寫檔案到磁碟。例如,您可能需要在應用重新啟動後保留資料,或者從網際網路下載資料並將其儲存以供以後離線使用。
要在移動或桌面應用中將檔案儲存到磁碟,請將 path_provider 外掛與 dart:io 庫結合使用。
本示例將採取以下步驟
- 查詢正確的本地路徑。
- 建立檔案位置的引用。
- 向檔案寫入資料。
- 從檔案讀取資料。
要了解更多資訊,請觀看本週熱門軟體包影片,介紹 path_provider 包。
1. 查詢正確的本地路徑
#此示例顯示了一個計數器。當計數器更改時,將資料寫入磁碟,以便您在應用載入時可以再次讀取它。您應該在哪裡儲存這些資料?
path_provider 包提供了一種平臺無關的方式來訪問裝置檔案系統中常用的位置。該外掛目前支援訪問兩個檔案系統位置:
- 臨時目錄
- 臨時目錄(快取),系統可以隨時清除。在 iOS 上,這對應於
NSCachesDirectory。在 Android 上,這是getCacheDir()返回的值。 - 文件目錄
- 應用程式用於儲存只能由其訪問的檔案目錄。系統僅在刪除應用程式時才會清除該目錄。在 iOS 上,這對應於
NSDocumentDirectory。在 Android 上,這是AppData目錄。
此示例將資訊儲存在文件目錄中。您可以透過以下方式找到文件目錄的路徑:
dart
import 'package:path_provider/path_provider.dart';
// ···
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}2. 建立檔案位置的引用
#一旦您知道要儲存檔案的位置,就建立一個指向檔案完整位置的引用。您可以使用 File 類,它來自 dart:io 庫來實現此目的。
dart
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/counter.txt');
}3. 向檔案寫入資料
#現在您有了一個可以使用的 File,請使用它來讀寫資料。首先,將一些資料寫入檔案。計數器是一個整數,但使用 '$counter' 語法作為字串寫入檔案。
dart
Future<File> writeCounter(int counter) async {
final file = await _localFile;
// Write the file
return file.writeAsString('$counter');
}4. 從檔案讀取資料
#現在您在磁碟上有一些資料,可以讀取它。同樣,使用 File 類。
dart
Future<int> readCounter() async {
try {
final file = await _localFile;
// Read the file
final contents = await file.readAsString();
return int.parse(contents);
} catch (e) {
// If encountering an error, return 0
return 0;
}
}完整示例
#dart
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(
MaterialApp(
title: 'Reading and Writing Files',
home: FlutterDemo(storage: CounterStorage()),
),
);
}
class CounterStorage {
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/counter.txt');
}
Future<int> readCounter() async {
try {
final file = await _localFile;
// Read the file
final contents = await file.readAsString();
return int.parse(contents);
} catch (e) {
// If encountering an error, return 0
return 0;
}
}
Future<File> writeCounter(int counter) async {
final file = await _localFile;
// Write the file
return file.writeAsString('$counter');
}
}
class FlutterDemo extends StatefulWidget {
const FlutterDemo({super.key, required this.storage});
final CounterStorage storage;
@override
State<FlutterDemo> createState() => _FlutterDemoState();
}
class _FlutterDemoState extends State<FlutterDemo> {
int _counter = 0;
@override
void initState() {
super.initState();
widget.storage.readCounter().then((value) {
setState(() {
_counter = value;
});
});
}
Future<File> _incrementCounter() {
setState(() {
_counter++;
});
// Write the variable as a string to the file.
return widget.storage.writeCounter(_counter);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Reading and Writing Files')),
body: Center(
child: Text('Button tapped $_counter time${_counter == 1 ? '' : 's'}.'),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}