Dart文件操作与命令行工具入门教程
时间:2026-08-21 | 作者:电竞小硕 | 阅读:0之前的课程,我们学习了库与包管理,掌握了代码组织和依赖管理的关键技能。
今天,咱们来探索Dart在文件操作和命令行工具开发方面的能力。这些技能在数据处理、自动化脚本、工具开发等场景里相当实用,能大幅提升你的开发效率。
一、文件操作基础:使用 dart:io 库
核心工具是 dart:io。
Dart 标准库中的 dart:io 提供了丰富的文件和目录操作 API,支持读取、写入、删除文件以及目录管理等功能。
1. 引入 dart:io 库
使用文件操作前,需要先导入 dart:io 库:
import 'dart:io';
2. 读取文件内容
读取文件有多种方式。
可以根据文件大小和实际需求,选择合适的方法。
(1)一次性读取小文件
在项目根目录下新建example.txt,写入任意内容。
对于小型文本文件,可以用 readAsString() 一次性读取全部内容:
import 'dart:io';
void main() async {
// 定义文件路径
final file = File('example.txt');
try {
// 读取文件内容(异步操作)
String content = await file.readAsString();
print('文件内容:');
print(content);
} catch (e) {
print('读取文件失败:$e');
}
}
(2)按行读取文件
在项目根目录下新建large_file.txt,写入任意内容。
对于大型文件,按行读取更高效,能避免占用过多内存:
import 'dart:convert';
import 'dart:io';
void main() async {
final file = File('large_file.txt');
try {
// 按行读取(返回 Stream)
Stream<String> lines = file
.openRead()
.transform(utf8.decoder)
.transform(LineSplitter());
await for (String line in lines) {
print('行内容:$line');
// 可以在这里添加处理逻辑,如查找特定内容
}
} catch (e) {
print('读取文件失败:$e');
}
}
需要额外导入编码和行分割器:
import 'dart:convert'; // 提供 utf8 编码
3. 写入文件内容
写入文件同样有多种方式。
既支持覆盖写入,也支持追加内容。
(1)覆盖写入文件
import 'dart:io';
void main() async {
final file = File('output.txt');
try {
// 写入字符串(覆盖原有内容)
await file.writeAsString('Hello, Dart 文件操作!n这是第二行内容');
print('文件写入成功');
} catch (e) {
print('文件写入失败:$e');
}
}
(2)追加内容到文件
import 'dart:io';
void main() async {
final file = File('output.txt');
try {
// 追加内容(mode: FileMode.append)
await file.writeAsString('n这是追加的内容', mode: FileMode.append);
print('内容追加成功');
} catch (e) {
print('追加失败:$e');
}
}
(3)写入字节数据
根目录下放入一张original_image.png图片。
对于二进制文件(如图片、音频),使用 writeAsBytes():
import 'dart:io';
void main() async {
final imageFile = File('image_copy.png');
final sourceFile = File('original_image.png');
try {
// 读取字节数据
List<int> bytes = await sourceFile.readAsBytes();
// 写入字节数据
await imageFile.writeAsBytes(bytes);
print('二进制文件复制成功');
} catch (e) {
print('文件复制失败:$e');
}
}
4. 目录操作
除了文件,dart:io 也支持目录的创建、删除和遍历:
import 'dart:io';
void main() async {
// 定义目录路径
final dir = Directory('my_files');
// 检查目录是否存在
if (!await dir.exists()) {
// 创建目录(recursive: true 表示创建多级目录)
await dir.create(recursive: true);
print('目录创建成功');
}
// 遍历目录中的文件和子目录
await for (FileSystemEntity entity in dir.list()) {
if (entity is File) {
print('文件:${entity.path}');
} else if (entity is Directory) {
print('目录:${entity.path}');
}
}
// 删除目录(recursive: true 表示删除目录及其中所有内容)
// await dir.delete(recursive: true);
// print('目录删除成功');
}
二、命令行参数解析:使用 args 包
开发命令行工具时,往往需要解析用户输入的参数。
比如 --help、-o output.txt 这类参数。
在Dart生态里,args 包无疑是处理命令行参数的不二之选。
1. 添加 args 依赖
在 pubspec.yaml 中添加依赖:
dependencies:
args: ^2.7.0
执行 dart pub get 安装依赖。
2. 基本参数解析
import 'package:args/args.dart';
void main(List<String> arguments) {
// 创建参数解析器
final parser = ArgParser()
..addFlag('help', abbr: 'h', help: '显示帮助信息', negatable: false)
..addOption('output', abbr: 'o', help: '指定输出文件路径')
..addOption(
'mode',
help: '运行模式',
allowed: ['debug', 'release'],
defaultsTo: 'debug',
);
try {
// 解析参数
final results = parser.parse(arguments);
// 处理 --help 参数
if (results['help'] as bool) {
print('使用方法:dart script.dart [选项]');
print(parser.usage);
return;
}
// 获取其他参数值
print('输出文件:${results['output'] '未指定'}');
print('运行模式:${results['mode']}');
print('位置参数:${results.rest}'); // 未解析的位置参数
} on FormatException catch (e) {
print('参数错误:$e');
print('使用 --help 查看帮助');
}
}
参数类型说明:
addFlag:布尔值参数(如--help),abbr表示短选项(如-h)addOption:带值的选项(如--output file.txt)results.rest:获取未解析的位置参数
运行示例:
dart script.dart -o result.txt --mode release input1.txt input2.txt
输出:
输出文件:result.txt
运行模式:release
位置参数:[input1.txt, input2.txt]
三、实战:批量重命名文件脚本
结合文件操作和命令行参数解析,我们来开发一个实用的批量重命名工具。
该工具支持以下功能:
- 指定目标目录
- 添加前缀 / 后缀
- 按序号重命名
- 预览重命名效果(不实际修改)
完整代码实现
import 'dart:io';
import 'package:args/args.dart';
import 'package:path/path.dart' as path;
void main(List<String> arguments) async {
// 创建参数解析器
final parser = ArgParser()
..addFlag('help', abbr: 'h', help: '显示帮助信息', negatable: false)
..addFlag('preview', abbr: 'p', help: '预览重命名效果,不实际修改', negatable: false)
..addOption('dir', abbr: 'd', help: '目标目录路径', defaultsTo: '.')
..addOption('prefix', abbr: 'x', help: '文件名前缀')
..addOption('suffix', abbr: 's', help: '文件名后缀')
..addFlag('number', abbr: 'n', help: '添加序号', negatable: false)
..addOption('start', abbr: 't', help: '序号起始值', defaultsTo: '1');
try {
final results = parser.parse(arguments);
// 显示帮助信息
if (results['help'] as bool) {
print('批量重命名工具');
print('用法:dart rename.dart [选项]');
print(parser.usage);
return;
}
// 解析参数
final previewMode = results['preview'] as bool;
final targetDir = Directory(results['dir'] as String);
final prefix = results['prefix'] as String '';
final suffix = results['suffix'] as String '';
final addNumber = results['number'] as bool;
final startNumber = int.tryParse(results['start'] as String) 1;
// 检查目录是否存在
if (!await targetDir.exists()) {
print('错误:目录不存在 - ${targetDir.path}');
return;
}
// 获取目录中的文件(排除子目录)
final files = await targetDir
.list()
.where((entity) => entity is File)
.toList();
files.sort((a, b) => a.path.compareTo(b.path)); // 按路径排序
if (files.isEmpty) {
print('目录中没有文件:${targetDir.path}');
return;
}
// 批量重命名
print('${previewMode '预览' : '执行'}重命名(共 ${files.length} 个文件):');
int currentNumber = startNumber;
for (final file in files.cast()) {
// 获取文件名和扩展名
final fileName = path.basename(file.path);
final extension = fileName.contains('.')
'.${fileName.split('.').last}'
: '';
final baseName = extension.isNotEmpty
fileName.substring(0, fileName.length - extension.length)
: fileName;
// 构建新文件名
String newName = '$prefix$baseName$suffix';
if (addNumber) {
newName = '${newName}_$currentNumber';
currentNumber++;
}
newName += extension;
// 构建新路径
final newPath = '${targetDir.path}${Platform.pathSeparator}$newName';
// 显示或执行重命名
print('${file.path} → $newPath');
if (!previewMode && file.path != newPath) {
await file.rename(newPath);
}
}
print('${previewMode '预览' : '重命名'}完成');
} on FormatException catch (e) {
print('参数错误:$e');
print('使用 --help 查看帮助');
} catch (e) {
print('操作失败:$e');
}
}
代码解析
- 参数定义:通过
args包定义了多种参数,满足不同重命名需求。 - 目录检查:验证目标目录是否存在,避免错误。
- 文件处理:
- 过滤出目录中的文件(排除子目录)
- 按路径排序,确保重命名顺序一致
- 文件名构建:
- 分离文件名和扩展名
- 根据前缀、后缀、序号等参数生成新文件名
- 执行重命名:支持预览模式(仅显示效果)和实际执行模式。
使用示例
- 预览当前目录文件添加前缀 "photo_" 并加序号的效果:
dart rename.dart -p -x photo_ -n
- 对
images目录的文件添加后缀 "_edited":
dart rename.dart -d images -s _edited
四、其他实用文件操作技巧
1. 获取文件信息
import 'dart:io';
void printFileInfo(File file) async {
final stat = await file.stat();
print('路径:${file.path}');
print('大小:${stat.size} 字节');
print('修改时间:${stat.modified}');
print('是否为文件:${stat.type == FileSystemEntityType.file}');
}
2. 复制文件
import 'dart:io';
Future<void> copyFile(String sourcePath, String targetPath) async {
final source = File(sourcePath);
final target = File(targetPath);
if (await source.exists()) {
await source.copy(targetPath);
print('复制成功:$targetPath');
} else {
print('源文件不存在:$sourcePath');
}
}
3. 递归遍历目录
import 'dart:io';
import 'package:path/path.dart' as path;
Future<void> listAllFiles(Directory dir, {int indent = 0}) async {
final spaces = ' ' * indent;
await for (final entity in dir.list()) {
if (entity is Directory) {
print('${spaces}目录:${entity.path}');
// 递归遍历子目录
await listAllFiles(entity, indent: indent + 1);
} else if (entity is File) {
print('${spaces}文件:${path.basename(entity.path)}');
}
}
}
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- Debian中cmatrix设置步骤
- 时间:2026-08-31
-
- Debian系统dumpcap命令行参数详解与实战指南
- 时间:2026-08-31
-
- VSCode运行Dart命令行工具如何配置Dart SDK环境变量
- 时间:2026-08-17
-
- 字节跳动火山引擎方舟CLI命令行工具详解
- 时间:2026-07-28
精选合集
更多大家都在玩
热门话题
大家都在看
更多-
- 神明蜕变逆袭RPG《星途天城》正式公测,强力神话星灵签到送,新手也能全图鉴!
- 时间:2026-10-22
-
- 蚂蚁新村小课堂今日答案10月22日 光伏发电运维值班员管理的是什么能源
- 时间:2026-10-22
-
- 蚂蚁新村2026年10月22日答案最新
- 时间:2026-10-22
-
- 蚂蚁庄园答案2026年10月23日
- 时间:2026-10-22
-
- 蚂蚁庄园今天答题答案2026年10月23日
- 时间:2026-10-22
-
- 蚂蚁庄园今日答案2026年10月23日
- 时间:2026-10-22
-
- “菊花霜"指的是秋季的哪一场霜 蚂蚁庄园今日答案10.23
- 时间:2026-10-22
-
- 小鸡答题今天的答案是什么2026年10月23日
- 时间:2026-10-22
