c++ 使用管道读取子进程的输出 不完整

2021-01-30 13:50:45 +08:00
 v2yllhwa

需要读取 ffmpeg 解码的输出来做一个进度条。
用 CreateProcess 来创建子进程,匿名管道重定向了 stdout 和 stderr,但是间歇性地会出现 strstr 找到了“Duration:”,但是此时 ReadBuff 里面就只有“Duration:”的情况。这种情况下再 ReadFile 也读不出来数据。

有什么头绪吗?

我的核心代码如下

    bRet = CreateProcess(NULL, (LPSTR)"ffmpeg.exe -i test.mkv output.mp4 -y", NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi);
    SetStdHandle(STD_OUTPUT_HANDLE, hTemp);
    CloseHandle(hWrite);
    while (ReadFile(hRead, ReadBuff, 1024, &ReadNum, NULL))
    {
        ReadBuff[ReadNum] = '\0';
        if (strstr(ReadBuff, "Duration:"))
        {
            for(int i=0;i<=10;i++)
        	{
        		putchar(*(strstr(ReadBuff, "Duration:")+10+i));
		}
		putchar('\n');
        }
    }

2544 次点击
所在节点    C++
24 条回复
whi147
2021-01-31 13:47:58 +08:00
还有你这个创建子进程方案还会遇到兼容性问题,最好用后缀是 ex 的函数
ysc3839
2021-01-31 19:37:02 +08:00
@whi147 CreateProcess 没有带 Ex 的版本,没有特殊需求的话用这个是没问题的。
no1xsyzy
2021-01-31 21:23:56 +08:00
@v2yllhwa 看了一下 man 7 pipe
POSIX 规范中要求短于 PIPE_BUF 的 write 操作是原子的。(这个值要求至少 512,Linux 上是 4096 )
v2yllhwa
2021-02-01 00:18:55 +08:00
感谢诸位的帮助。因为是在 qt 里面写,本来想先把核心代码搞通顺再封装进去来着,今天晚上晕头转向用 QProcess 来实现居然完美解决了?!有时间我再深入研究下各位说的问题。
现在的代码~ (比起之前 CreateProcess 既方便还更兼容)
```c++
process.start(ffmpegPath,params);
waitResult = process.waitForStarted();
process.setReadChannel(QProcess::StandardError);
......
bufferLength=process.readLine(buffer,1024);
if(output.indexOf("Duration:")!=-1)
{
videoSeconds = output.mid(12,2).toInt()*60*60+output.mid(15,2).toInt()*60+output.mid(18,2).toInt();
}
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/749817

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX