You need to enable JavaScript to run this app. C#使用Process调用rclone获取实时输出时首字符单独输出问题
优惠活动
大模型
产品
解决方案
定价
更多

C#使用Process调用rclone获取实时输出时首字符单独输出问题

问题成因与解决方案

成因说明

该问题不是rclone的特性导致,是两个实现逻辑的叠加问题:

  • 流读取本身存在天然分片特性:你所用的AsyncStreamReader是直接从进程输出的基础流读取字节,操作系统、进程输出缓冲的机制本身不会保证一次性返回整行/整条消息的所有字节,首字母T刚好是第一次BeginRead返回的1个字节,剩余内容会在后续读取回调中返回,这是流读取的正常现象。
  • 日志写入逻辑不合理:当前你拿到每一段分片数据就直接调用writeToLog追加一行,自然会把单独的T当成一行输出,剩余内容被识别为下一行。

解决方案

方案1:AsyncStreamReader层面新增缓冲拼接(推荐)

修改AsyncStreamReader类,增加内部缓冲区暂存读取到的不完整内容,检测到完整行分隔符后再触发数据接收事件,修改后的核心代码如下:

class AsyncStreamReader
{
    public delegate void EventHandler<args>(object sender, string Data);
    public event EventHandler<string> DataReceived;

    protected readonly byte[] buffer = new byte[4096];
    private StreamReader reader;
    private readonly StringBuilder _readBuffer = new StringBuilder(); // 新增内部缓冲字段

    public bool Active { get; private set; }

    // 其他原有构造、Start、Stop、BeginReadAsync方法保持不变,仅修改ReadCallback
    private void ReadCallback(IAsyncResult asyncResult)
    {
        int bytesRead = reader.BaseStream.EndRead(asyncResult);

        if (bytesRead > 0)
        {
            string data = reader.CurrentEncoding.GetString(buffer, 0, bytesRead);
            _readBuffer.Append(data);

            // 拆分所有完整行输出
            while (true)
            {
                int newlineIndex = _readBuffer.ToString().IndexOfAny(new[] { '\r', '\n' });
                if (newlineIndex < 0) break; // 没有完整行,等待后续读取

                string completeLine = _readBuffer.ToString(0, newlineIndex).TrimEnd('\r');
                _readBuffer.Remove(0, newlineIndex + 1);

                if (!string.IsNullOrEmpty(completeLine) && DataReceived != null)
                {
                    DataReceived.Invoke(this, completeLine);
                }
            }
        }
        else
        {
            Active = false;
            // 进程退出后输出缓冲中剩余的内容
            if (_readBuffer.Length > 0 && DataReceived != null)
            {
                DataReceived.Invoke(this, _readBuffer.ToString().TrimEnd('\r', '\n'));
                _readBuffer.Clear();
            }
        }

        if (Active)
        {
            BeginReadAsync();
        }
    }

    // 其他原有代码保持不变
}

修改后你的事件订阅逻辑不需要做任何改动,就能收到完整的行内容。

方案2:适配rclone输出特性

你用了-P参数开启实时进度显示,rclone默认用回车符\r重写同一行更新进度,你可以在启动参数中添加--stats-one-line简化进度输出,或者替换-P为-v输出结构化日志,避免单行反复刷新带来的内容拆分问题。

内容的提问来源于stack exchange,提问作者Min Gu Kang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 03:27:03