Working with Files in Flutter
Tags: flutter
Published: 2023-07-07 12:32:33

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](https://youtu.be/J2LYTHE3bUo) and [Odysee](https://odysee.com/@svprdga:d/working-with-files-in-flutter)

{% embed https://youtu.be/J2LYTHE3bUo %}

### List common directories

By using the [path\_provider](https://pub.dev/packages/path_provider) plugin we can get the path to common directories designed for different purposes:

```dart
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:

```dart
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.

```dart
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:

```dart
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:

```dart
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:

```dart
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:

```dart
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:

```dart
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:

```dart
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:

```dart
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:

```dart
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!