To write to a file in Flutter, you will be combining some Dart libraries with the Flutter SDK. You need the Flutter component to let you know where to write your file, while you need the Dart Libraries to actually perform the IO operations.
In Flutter, the path_provider
provides a platform agnostic way to access files. This is needed as each platform stores them in a different location.
A temporary directory (cache) is a directory that the system can clear at any time. On iOS, this corresponds to the NSCachesDirectory
. On Android, this is the value that getCacheDir()
returns.
To get the path to temporary storage, you would use:
Future<String> get _localPath async {
Directory tempDir = await getTemporaryDirectory();
return tempDir.path;
}
A documents directory is available for the app to store files that only that app can access. The system clears the directory only when the app is deleted. On iOS, this corresponds to the NSDocumentDirectory
. On Android, this is the AppData
directory.
To get the path for a documents directory, you would use the code below:
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Creating the Base App
To create a sample app that reads and writes data to a file, we will start with the basic app we first create. I called my app: sample_file_access
.
Once the file is created, I’m going to go in and clean up all of the now unnecessary comments in the code, to make it easier to work with.
I will also go in and remove the floating action button and all related elements (counter, _incrementCounter, etc) so that we can focus on what we need for this app.
Create a Reference to the File
The next step will be to create a function which allows us to have access to the file. This function is fairly simple:
Future<File> get _localFile async {
final path = await _localPath;
return File('$path/data.txt');
}
If you type (or copy/paste) this in, you will notice several errors. You will need to add the dart IO library to make most of these go away.
import 'dart:io';
There should still be an issue to the _localPath variable. So we can fix that, but calling a function which gets that for us. I’m going to use the function above for the temporary path.
Of course, you cannot use the file directories without loading the path_provider library. So open up pubspec.yaml file and add this to the dependencies section, like we’ve done before.
path_provider: 2.0.4
Saving your file will download the library for you, and get you ready to go to import it into your code. When you are done, you’ll have several imports which you can see below:
import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
Writing Data to a File
Typically we might write log data info, or be writing something from within the code deep, but since this is sample data, we’re gong to write it inside the writeContent function, so it be used and ready when we need it to display the text.
After getting the file, we will use the .writeAsString()
method to write a line of text.
void main() async {
Future<File> writeContent() async {
final file = await _localFile;
// Write the file
file.writeAsString('O Captain! My Captain! our fearful trip is done;');
file.writeAsString(
'The ship has weather\'d every rack, the prize we sought is won;');
file.writeAsString(
'The port is near, the bells I hear, the people all exulting,');
file.writeAsString(
'While follow eyes the steady keel, the vessel grim and daring:');
return file;
}
Reading the File
A lot more information can be had at the File documentation, but for now, we’ll use a simple process to read the data.
We will put our contents into a try/catch block to protect against potential errors.
Future<String> readContents() async {
try {
final file = await _localFile;
// Read the file
final contents = await file.readAsString();
return contents;
} catch (e) {
// If encountering an error, return an empty string
return '';
}
}
This method was put inside of the class _MyHomePageState
. We also added a String variable called _contents, which will get the data from the readContents() method.
This did require changing the build method a bit, so instead of $_counter, it’s not $_contents, and we remove the Text Widget with a display for what the number represented, since it isn’t a number anymore.
Finally, we’ll need to update the initState, so we know when to read the file.
@override
void initState() {
super.initState();
writeContent().then((value) => readContents().then((String value) {
setState(() {
_contents = value;
});
}));
// );
}
Notes of Testing
While the path_provider
works for most systems (iOS, Android, Windows, etc) it doesn’t work for Web, so you have to have an emulator running to test this application.
Writing to a File with Flutter was originally found on Access 2 Learn