Dart中Process.start执行Appwrite初始化时如何获取完整stdout输出
Dart Process.start 完整获取stdout输出的解决方案
问题场景
使用Dart的Process.start自动化创建Appwrite项目时,stdout会以分块形式返回,部分块还包含终端刷新产生的重复内容,无法直接拿到完整输出。测试代码如下:
import 'dart:convert'; import 'dart:io'; void main(List<String> arguments) async { Process process = await Process.start( 'appwrite', ['init', 'project'], ); process.stdout.listen((event) { String s = utf8.decode(event); print(s); if (s.contains('Create a new Appwrite project')) { process.stdin.writeln(); } }); process.stderr.listen((event) { String s = utf8.decode(event); print(s); }); }
输出截图:
解决方案
1. 流式场景(需实时交互):用缓冲区收集所有输出
Process.start是流式API,操作系统会按缓冲区大小分块传输数据,必须将所有分块内容收集到缓冲区中才能获取完整输出。同时,检查交互触发条件时要基于完整缓冲区内容,避免因目标字符串被拆分到多个块中而错过触发时机。
示例代码:
import 'dart:convert'; import 'dart:io'; void main(List<String> arguments) async { final process = await Process.start('appwrite', ['init', 'project']); // 收集完整stdout内容的缓冲区 final stdoutBuffer = StringBuffer(); final utf8Decoder = Utf8Decoder(); // 监听stdout流,收集所有分块内容 process.stdout.listen((bytes) { final chunk = utf8Decoder.convert(bytes); stdoutBuffer.write(chunk); print(chunk); // 实时打印输出,可选 // 检查完整缓冲区是否包含目标字符串,触发交互 if (stdoutBuffer.toString().contains('Create a new Appwrite project')) { process.stdin.writeln(); } }); // 监听stderr输出 process.stderr.listen((bytes) => print(utf8.decode(bytes))); // 等待进程结束 final exitCode = await process.exitCode; print('进程退出码: $exitCode'); // 获取完整的stdout内容 final fullStdout = stdoutBuffer.toString(); print('\n=== 完整输出内容 ==='); print(fullStdout); // 可选:过滤终端ANSI控制字符(移除刷新/格式控制内容) final cleanOutput = fullStdout.replaceAll(RegExp(r'\x1B\[[0-?]*[ -/]*[@-~]'), ''); print('\n=== 清理后输出 ==='); print(cleanOutput); }
2. 非流式场景(无需实时交互):使用Process.run
如果不需要实时处理进程输出,只是想一次性获取完整结果,可以用Process.run替代Process.start,该方法会等待进程执行完毕后返回所有输出内容。
示例代码:
import 'dart:convert'; import 'dart:io'; void main(List<String> arguments) async { // 执行命令,传入所需的输入内容 final result = await Process.run( 'appwrite', ['init', 'project'], stdin: utf8.encode('\n'), // 模拟用户输入回车 runInShell: true, // 部分环境下需要启用shell执行 ); print('=== 标准输出 ==='); print(result.stdout); print('\n=== 标准错误 ==='); print(result.stderr); print('\n退出码: ${result.exitCode}'); }
说明
出现分块/重复内容的原因是Appwrite CLI使用了终端交互库,会输出ANSI控制字符来刷新终端界面,这些控制字符会被当作输出内容返回。如果需要纯净的输出,可以用正则表达式过滤掉这些控制字符(如上述示例中的cleanOutput部分)。
内容的提问来源于stack exchange,提问作者Develocode 777
相关产品推荐
相关产品推荐

