在数据进入块时获取线路的最简单方法是什么?

时间:2011-02-05 00:29:04

标签: c++ stl stream

我正在使用win32的ReadFile来读取子进程的管道。这一次给了我一大块字符和每个块的大小,但它们可能有也可能没有新行。我想逐行处理输出。这样做最简单的方法是什么?

我考虑将每个块附加到string,最后使用stringstream逐行处理它,但我想在数据进入时执行此操作。我想诀窍是,我应该如何以及在哪里检测到新的行结束?如果在找不到分隔符时只有streamreader的{​​{1}}没有返回任何内容......

3 个答案:

答案 0 :(得分:1)

追加到字符串,直到遇到换行符或数据结尾。然后你在字符串中有一行,处理它,空字符串并重复。使用字符串的原因:您不知道一行可能有多长,并且字符串会根据需要为您重新分配等。

特殊情况:在该行之前没有任何内容的数据结尾可能不是一行,而是被忽略。

干杯&第h

答案 1 :(得分:0)

我能想到的是使用缓冲区来存储块,你知道通过lpNumberOfBytesRead的大小,所以在每个块上你检查它是否包含新的行字符,如果它包含,你输出所有的将字符缓冲到新行字符,然后开始缓冲,直到收到另一个带有新行字符的块,依此类推。

某些伪代码可能如下所示:

w_char buffer[BUFFER_SIZE]; // enough for few chunks (use new to allocate dynamic memory)
ReadLine(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
if (w_char has new_line_character) {
    process_whole_line(); // don't forget to clear up the buffer
}

答案 2 :(得分:0)

您可以扩展std::basic_streambuf并实施xsputn,以便将数据存储在内部缓冲区中,并检测换行符或执行您需要的任何处理。如果您只想处理完整的行,检测到后可以将缓冲区推到std::queue直到换行符,并从缓冲区中删除相应的部分。您还需要实施overflow。例如:

template<typename CharT, typename Traits = std::char_traits<CharT> >
class line_streambuf : public std::basic_streambuf<CharT, Traits> {
public:
    typedef CharT                           char_type;
    typedef Traits                          traits_type;
    typedef std::basic_string<char_type>    string_type;
    typedef typename string_type::size_type size_type;
    typedef typename traits_type::int_type  int_type;
    line_streambuf(char_type separator = '\n') : _separator(separator) {}
    virtual ~line_streambuf() {}
    bool getline(string_type& output) { /* pop from the queue and return */ }
protected:
    virtual int_type overflow(int_type v) {
        if (v == _separator) {
            _processed.push(_buffer);
            _buffer.erase(_buffer.begin(), _buffer.end());
        } else {
            _buffer += v;
        }
        return v;
    }
    virtual std::streamsize xsputn(const char_type* p, std::streamsize n) {
        _buffer.append(p, p + n);
        while (true) {
            // The 1st find could be smarter - finding only after old_length+p
            size_type pos = _buffer.find(_separator);
            if (pos == string_type::npos)
                break;
            _processed.push(string_type(_buffer.begin(), _buffer.begin()+pos));
            _buffer.erase(_buffer.begin(), _buffer.begin() + pos + 1);
        }
        return n;
    }
private:
    char_type _separator;
    string_type _buffer;
    std::queue<string_type> _processed;
};

注意:高度未经测试的代码。如果您发现问题或者随时可以编辑,请告诉我。