c++ - 无法从通过管道 C++ (Windows) 重定向的程序中获得正确的输出

标签 c++ windows pipe createprocess

我想实现一个结果,以便程序的输出拆分为双端队列结构。

问题描述:我正在处理重定向使用 CreateProcess 创建的程序的输出。我需要读取程序的输出并逐行处理它。该程序本身以方便的形式提供输出,但我通过未命名管道接收的输出传送速度较慢(频率较低),它们出现在部分中,并且最后一行在某处被减半。来自管道的下一部分流将匹配并完成该行,但它会给程序的构建带来一些问题。

程序的 cout 和通过管道重定向的输出之间存在这种差异的原因是什么?

编辑:根据提议 user4581301我试过使用 stringstream 和 getline,但似乎这些行仍然被切成两半,即使从程序直接 cout 而没有重定向到管道没有这个问题。这导致了问题,行在队列的不同元素中被拆分(请查看下面的代码)。

Sample from the console

ReadFromPipe 方法在循环中运行。

void ProcessManagement::ReadFromPipe(void)

// Read output from the child process's pipe for STDOUT

{
    DWORD dwRead, dwWritten;
    char buffer[BUFSIZE];
    BOOL bSuccess = FALSE;
    std::deque<std::deque<std::string>> elems;

while (ReadFile(g_hChildStd_OUT_Rd, buffer, sizeof(buffer)-1, &dwRead, NULL) != FALSE)
{
    /* add terminating zero */
    buffer[dwRead] = '\0';
    std::stringstream streamBuffer;
    streamBuffer << buffer;
    BufferToQueue(streamBuffer, ' ', elems);

    // Print deque
    for (std::deque <std::string> a : elems)
    {
        for (std::string b : a)
            std::cout << b;
        std::cout << std::endl;
    }

    }
}

和 BufferToQueue 方法。

void ProcessManagement::BufferToQueue(std::stringstream &streamBuffer, char delim, std::deque<std::deque<std::string>> &elems) {
    std::string line;
    std::string word;
    std::deque<string> row;

 // Splitting the stringstream into queue of queue (does not work properly)
    while (std::getline(streamBuffer, line))
    {
        std::istringstream iss(line);
        while (std::getline(iss, word, delim))
            row.push_back(word);
    elems.push_back(row);
    row.clear();
    }
}

最佳答案

扩展@Captain Obvlious 关于同花顺的评论:

您遇到的问题是因为 WriteToPipe 函数没有在行尾刷新。如果先前的 ReadFromPipe 调用没有将 newline 作为最后一个字符,您可以通过确保追加到先前的字符串来在阅读器中解决此问题。

修改后的功能:

bool ProcessManagement::BufferToQueue(std::stringstream &streamBuffer, char     delim, std::deque<std::deque<std::string>> &elems)
{
    std::string line;
    std::string word;
    std::deque<string> row;

    bool is_unflushed_line = streamBuffer.str().back() != '\n';

    // Splitting the stringstream into queue of queue (does not work properly)
    while (std::getline(streamBuffer, line))
    {
        std::istringstream iss(line);
        while (std::getline(iss, word, delim)) {
            row.push_back(word);
        }
        elems.push_back(row);
        row.clear();
    }
    return is_unflushed_line;
}

void ProcessManagement::ReadFromPipe(void)
// Read output from the child process's pipe for STDOUT
{
    DWORD dwRead, dwWritten;
    char buffer[BUFSIZE];
    BOOL bSuccess = FALSE;
    std::deque<std::deque<std::string>> elems;

    while (ReadFile(g_hChildStd_OUT_Rd, buffer, sizeof(buffer)-1, &dwRead, NULL) != FALSE)
    {
        /* add terminating zero */
        buffer[dwRead] = '\0';
        std::stringstream streamBuffer;
        streamBuffer << buffer;
        bool is_unflushed_line = BufferToQueue(streamBuffer, ' ', elems);

        for(auto idx = 0; idx != elems.size(); ++idx)
        {
            for (std::string const& b : elems[idx])
                std::cout << b;
            if(idx == elems.size() - 1 && is_unflushed_line)
                break;// don't print a newline if input did not end with a newline
            std::cout << std::endl;
        }
    }
}

关于c++ - 无法从通过管道 C++ (Windows) 重定向的程序中获得正确的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42380376/

相关文章:

C++ 使用裸函数

C++ 从函数返回值

windows - 创建 QEmu guest 操作系统的 WinDbg 可读转储

java - "Low level"使用Java的项目

sockets - 套接字与管道的性能

c - 管道和标准输出

bash - 使用管道时修改文件的最佳方法?

c++ - openann C++编译失败

windows - 如何在使用 Visual C++ 2010 命令提示符时包含/链接 DLL

c++ - 当通过引用访问时,Constexpr 成员函数返回不被视为 constexpr 的模板参数