Introduction
Dart's dart:io library provides the File class for reading and writing files on the filesystem. File operations are asynchronous (return Futures) and synchronous (with Sync suffix). Always prefer async versions in production code.
Note: dart:io is available only in Dart native (CLI, server, Flutter). It is NOT available in Dart web/DartPad.
Reading Files
import 'dart:io';
Future<void> readExamples() async {
var file = File('example.txt');
// Read entire file as String:
String content = await file.readAsString();
print(content);
// Read line by line (efficient for large files):
List<String> lines = await file.readAsLines();
for (var line in lines) {
print(line);
}
// Read as bytes:
List<int> bytes = await file.readAsBytes();
print('File size: $${bytes.length} bytes');
// Stream large files (memory-efficient):
var stream = file.openRead();
await for (var chunk in stream) {
// process chunk (List<int>)
}
}
Writing Files
Future<void> writeExamples() async {
var file = File('output.txt');
// Write a string (overwrites existing content):
await file.writeAsString('Hello, Dart File I/O!\n');
// Write with encoding:
await file.writeAsString(
'Second write',
mode: FileMode.write, // default — overwrite
encoding: const Utf8Codec(),
);
// Write bytes:
await file.writeAsBytes([72, 101, 108, 108, 111]); // 'Hello' in ASCII
}
Appending to Files
Future<void> appendExample() async {
var file = File('log.txt');
var timestamp = DateTime.now().toIso8601String();
await file.writeAsString(
'$timestamp - Log entry\n',
mode: FileMode.append, // append instead of overwrite
);
}
Checking and Deleting Files
Future<void> fileManagement() async {
var file = File('temp.txt');
// Check existence:
bool exists = await file.exists();
print('Exists: $exists');
// Get file stat:
var stat = await file.stat();
print('Size: $${stat.size} bytes');
print('Modified: $${stat.modified}');
// Copy a file:
await file.copy('temp_backup.txt');
// Rename/move:
var renamed = await file.rename('renamed.txt');
print('Renamed to: $${renamed.path}');
// Delete:
if (await renamed.exists()) await renamed.delete();
// Working with directories:
var dir = Directory('my_folder');
await dir.create(recursive: true);
var listing = await dir.list().toList();
print('Files: $${listing.length}');
}
Full Example: CSV Logger
import 'dart:io';
class CsvLogger {
final File _file;
CsvLogger(String path) : _file = File(path);
Future<void> initialize() async {
if (!await _file.exists()) {
await _file.writeAsString('timestamp,level,message\n');
}
}
Future<void> log(String level, String message) async {
var row = '$${DateTime.now().toIso8601String()},$level,"$message"\n';
await _file.writeAsString(row, mode: FileMode.append);
}
Future<List<String>> readLogs() => _file.readAsLines();
}
Future<void> main() async {
var logger = CsvLogger('app.log');
await logger.initialize();
await logger.log('INFO', 'Application started');
await logger.log('WARNING', 'Low memory');
await logger.log('ERROR', 'Connection refused');
var logs = await logger.readLogs();
logs.forEach(print);
}
🧠 Quiz
1. Which FileMode appends to an existing file instead of overwriting?
- A) FileMode.write
- B) FileMode.append ✅
- C) FileMode.add
- D) FileMode.open
2. Which dart:io class is used for file operations?
- A) IO
- B) FileSystem
- C) File ✅
- D) FileHandler
Summary
Use dart:io's File class for reading (readAsString, readAsLines, readAsBytes) and writing (writeAsString, writeAsBytes). Use FileMode.append to add to existing files. Always check file.exists() before operations. Use streaming APIs for large files to avoid loading everything into memory.