Консоль, файлы и HTTP в Dart
Консоль, файлы и HTTP в Dart
Dart часто воспринимают только через Flutter, но тот же язык подходит для консольных утилит, скриптов автоматизации и лёгких серверов. Для этого используют библиотеку dart:io (доступна в Dart VM на десктопе и сервере; в браузерной сборке её нет — там другие API).
Связанные темы: первая программа, асинхронность, архитектура и dart:io.
Консольный ввод и вывод
Вывод в терминал — функция print из dart:core (уже в первой программе). Для потоков без буферизации и stderr:
import 'dart:io';
void main() {
stdout.writeln('Введите имя:');
final name = stdin.readLineSync()?.trim() ?? 'Гость';
stderr.writeln('(отладка: прочитано ${name.length} символов)');
print('Привет, $name!');
}
| API | Назначение |
|---|---|
stdout | Обычный вывод |
stderr | Сообщения об ошибках и диагностика |
stdin.readLineSync() | Строка до Enter (синхронно) |
В интерактивных CLI предпочтительнее асинхронное чтение, чтобы не блокировать event loop при сложной логике:
Future<void> main() async {
stdout.write('Число: ');
final line = await stdin.readLine();
final n = int.tryParse(line?.trim() ?? '');
if (n == null) {
print('Некорректный ввод');
return;
}
print('Квадрат: ${n * n}');
}
Шаблон проекта: dart create -t console my_tool — см. установку и запуск.
Работа с файлами и каталогами
Классы File, Directory из dart:io описывают пути в файловой системе.
Текст:
import 'dart:io';
Future<void> copyText(String from, String to) async {
final source = File(from);
if (!await source.exists()) {
throw FileSystemException('файл не найден', from);
}
final text = await source.readAsString();
await File(to).writeAsString(text);
}
Построчное чтение (логи, CSV):
Future<int> countLines(String path) async {
var count = 0;
await for (final _ in File(path).openRead().transform(utf8.decoder).transform(const LineSplitter())) {
count++;
}
return count;
}
Для utf8 и LineSplitter нужен import 'dart:convert';.
Каталоги:
Future<void> ensureDataDir() async {
final dir = Directory('data');
if (!await dir.exists()) {
await dir.create(recursive: true);
}
await for (final entity in dir.list()) {
print(entity.path);
}
}
Бинарные данные — readAsBytes / writeAsBytes; для больших файлов — потоки openRead() / openWrite() без загрузки всего файла в память.
JSON — сохранение и загрузка
Сериализация через dart:convert не требует сторонних пакетов для простых структур:
import 'dart:convert';
import 'dart:io';
Future<void> saveConfig(Map<String, Object?> config) async {
final json = jsonEncode(config);
await File('config.json').writeAsString(json);
}
Future<Map<String, dynamic>> loadConfig() async {
final file = File('config.json');
if (!await file.exists()) return {};
final raw = await file.readAsString();
return jsonDecode(raw) as Map<String, dynamic>;
}
Для сложных моделей в production-проектах генерируют код (json_serializable, freezed); на этапе обучения достаточно ручного Map или record с явным маппингом полей.
HTTP-клиент
Встроенный HttpClient (dart:io) подходит для скриптов и сервисов без лишних зависимостей:
import 'dart:convert';
import 'dart:io';
Future<void> fetchExample() async {
final client = HttpClient();
try {
final request = await client.getUrl(Uri.parse('https://httpbin.org/get'));
final response = await request.close();
if (response.statusCode != 200) {
throw HttpException('код ${response.statusCode}');
}
final body = await response.transform(utf8.decoder).join();
final data = jsonDecode(body) as Map<String, dynamic>;
print(data['origin']);
} finally {
client.close(force: true);
}
}
В приложениях на Flutter чаще берут пакет http или dio — они проще в тестах и повторном использовании. Для консольного Dart достаточно HttpClient или package:http.
Всегда оборачивайте сетевые вызовы в try/catch и закрывайте клиент в finally, как в обработке ошибок.
Минимальный HTTP-сервер
Тот же dart:io позволяет поднять лёгкий сервер для учебных задач и локальных API:
import 'dart:io';
Future<void> main() async {
final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 8080);
print('Слушаем http://127.0.0.1:8080');
await for (final request in server) {
if (request.uri.path == '/health') {
request.response
..statusCode = HttpStatus.ok
..write('ok');
} else {
request.response.statusCode = HttpStatus.notFound;
}
await request.response.close();
}
}
Для реального бэкенда обычно выбирают фреймворки уровня Shelf, Serverpod или отдельный стек (Node, Go и т.д.); встроенный HttpServer полезен, чтобы понять цикл «запрос → ответ» без лишних слоёв. Общие принципы HTTP — в справочнике по HTTP энциклопедии.
Асинхронность и изоляты
Чтение файлов и сеть — операции ввода-вывода. Их выполняют через Future и async/await (функции и асинхронность), чтобы не блокировать единственный поток изолята. Тяжёный разбор большого файла можно вынести в Isolate.run, если утилита начинает «подвисать» на больших объёмах данных.
Ограничения платформ
| Среда | dart:io | Примечание |
|---|---|---|
| Консоль, сервер, desktop VM | Да | Основной сценарий статьи |
| Flutter mobile/desktop | Да | Плюс доступ к нативным API через плагины |
| Flutter Web / dart2js | Нет | Файлы и сокеты — через браузерные API и пакеты |
Перед переносом консольного скрипта в веб-проект проверьте, что код не импортирует dart:io без условной компиляции.
Типичные ошибки
- Забыли
awaitприreadAsString— получилиFuture, а не текст. - Путь к файлу без
Directory.current/Platform.pathSeparator— ломается при смене ОС. - Не закрыли
HttpClient— утечка сокетов при многократных запросах. - Синхронное
readLineSyncв UI-изоляте Flutter — риск подвисания интерфейса (там только асинхронные API).
Что изучить дальше
После консольного Dart логично углубить паттерны и switch для разбора ответов API и перейти к Flutter, если цель — пользовательские приложения. Для серверной разработки в экосистеме Dart смотрите также разделы энциклопедии про сети и бэкенд.
См. также
Другие статьи этого же раздела в боковом меню (как на странице «О разделе»). История Dart - возникновение языка в Google и его развитие как основы для Flutter-экосистемы. Инкапсуляция через _, late, конструкторы, factory, const, абстрактные классы, миксины и интерфейсы в Dart. Простые приложения на Dart — CLI, файлы, JSON и минимальный HTTP на dart:io. Dart выглядит как Java или C#, но есть свои привычки: точка с запятой в конце строки не обязательна, строки в "...", многострочные литералы '''. Основы Dart - точка входа `main`, базовый синтаксис и старт построения приложений на языке. Runtime Dart — система типов, isolates, event loop, JIT/AOT, сборка мусора, SDK и связка с Flutter. Flutter - экосистема Dart для кроссплатформенной UI-разработки, сборки и тестирования приложений. Типизация, набор правил определения типа данных значений языка. Условия, циклы, switch, арифметика, логика и null-aware операторы Dart — с примерами для Dart 3. Функция — это именованный фрагмент кода, который принимает входные данные, выполняет определённую последовательность действий и может возвращать результат. Гайд по установке и настройке с написанием первой программы и её запуском. Switch expressions, сопоставление с образцом для record, списков, Map и sealed-типов — исчерпывающий разбор вариантов в Dart 3.История языка Dart
Классы и ООП в Dart
Простые приложения на Dart
Синтаксис и пунктуация в Dart
Основы языка Dart
Архитектура платформы Dart
Flutter
Типы данных и безопасность типов
Управляющие конструкции и операторы Dart
Функции и асинхронность
Первая программа на Dart
Паттерны и switch в Dart 3