Working with Files in Flutter

Working with Files in Flutter

Odds are that if you work with Flutter, eventually you'll have to handle files and directories.

Let's do a quick summary of all the basic filesystem operations that we can do with Flutter:

📽 Video version available on YouTube and Odysee

List common directories

By using the path_provider plugin we can get the path to common directories designed for different purposes:

import 'package:path_provider/path_provider.dart';

// Put cache files in this directory
final temporaryDirectory = await getTemporaryDirectory();
// For files that our app uses but are not exposed to the user
final appSupport = await getApplicationSupportDirectory();
// For user-generated files
final appDocuments = await getApplicationDocumentsDirectory();

Create a file

Let's create a random file in the temporary directory and write something inside:

final Directory tempDir = await getTemporaryDirectory();
final File file = File('${tempDir.path}/sample_file.txt');

await file.writeAsString('Sample content to write');

Delete a file

The delete method is just as crucial as the create method, as it helps clear out old files and thus saves valuable storage space.

final Directory tempDir = await getTemporaryDirectory();
final File file = File('${tempDir.path}/sample_file.txt');

await file.delete();

Create a directory

Now let's say that I want to create a new file, but within a certain directory:

final Directory tempDir = await getTemporaryDirectory();
final Directory newDirectory =
    Directory('${tempDir.path}/sample_directory');

// Always check that the directory exists
if (await newDirectory.exists() == false) {
  await newDirectory.create();
}

final File file = File('${newDirectory.path}/sample_file.txt');
await file.writeAsString('Sample content to write');

Remove a directory

Now let's do the reverse and delete the directory:

final Directory tempDir = await getTemporaryDirectory();
final Directory newDirectory =
    Directory('${tempDir.path}/sample_directory');

await newDirectory.delete(recursive: true);

List files

Sometimes you need to list all files within a directory to get some of its stats:

final Directory directory = await getTemporaryDirectory();
final List<FileSystemEntity> files = directory.listSync();

for (final FileSystemEntity file in files) {
  final FileStat fileStat = await file.stat();
  print('Path: ${file.path}');
  print('Type: ${fileStat.type}');
  print('Changed: ${fileStat.changed}');
  print('Modified: ${fileStat.modified}');
  print('Accessed: ${fileStat.accessed}');
  print('Mode: ${fileStat.mode}');
  print('Size: ${fileStat.size}');
}

Read file

Let's open a file to see its content:

final Directory tempDir = await getTemporaryDirectory();
final File file = File('${tempDir.path}/sample_file.txt');

final String fileContent = await file.readAsString();

Copy file

Now, let's generate a duplicate of the previously created sample file:

final Directory tempDir = await getTemporaryDirectory();
final File file = File('${tempDir.path}/sample_file.txt');

final File copy = await file.copy('${tempDir.path}/copy_file.txt');

Rename file

Next, let's change the name of the file we just copied:

final Directory tempDir = await getTemporaryDirectory();
final File file = File('${tempDir.path}/copy_file.txt');

await file.rename('${tempDir.path}/new_name.txt');

Synchronously manage file operations

So far, I've demonstrated how to handle files asynchronously, which is the preferred method. However, if for some reason Futures aren't an option for you, synchronous file operations are also possible:

final Directory tempDir = await getTemporaryDirectory();
final File file = File('${tempDir.path}/sample_file.txt');

file.writeAsStringSync('New content to add');

Error handling

All file system operations should be performed safely since they are prone to throw exceptions. For simplicity, the previous examples did not include this, but it's critical to always encapsulate your I/O operations within a try-catch block:

final Directory tempDir = await getTemporaryDirectory();
final File file = File('${tempDir.path}/sample_file.txt');

try {
  await file.writeAsString('New content to add');
} catch (e) {
  // Handle IO error
}

Conclusion

Dart and Flutter simplify working with files, as demonstrated above. I hope this summary was useful and clear.

Happy coding!

Did you find this article valuable?

Support David Serrano by becoming a sponsor. Any amount is appreciated!