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

发布于 2024-10-16 03:06:53 字数 282 浏览 5 评论 0原文

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

我考虑过将每个块附加到一个 string 中,最后使用 stringstream 逐行处理它,但我想这样做,因为数据是我想诀窍是,我应该如何以及在哪里检测新行结尾?如果在找不到分隔符时,streamreadergetline 没有返回任何内容...

I am using win32's ReadFile to read from a child process's pipe. That gives me chunks of characters at a time and the size of each chunk, but they may or may not have new lines. I want to process the output line by line. What is the simplest way of doing so?

I thought about appending each chunk to a string, and at the end, using a stringstream to process it line by line, but I'd like to do this as data is coming in. I suppose the trick is, how and where should I detect the new line ending? If only streamreader's getline returned nothing when no delimiter is found...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

以为你会在 2024-10-23 03:06:53

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

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

干杯&嗯。

Append to a string until you encounter newline char or end of data. Then you have a line in the string, process it, empty string and repeat. Reason for using the string: that you don't know how long a line may be, and a string does the reallocation etc. for you as necessary.

Special case: end of data with nothing earlier on that line should probably be not-a-line, ignored.

Cheers & hth.

御弟哥哥 2024-10-23 03:06:53

我能想到的是使用一个缓冲区来存储传入您的块,您通过 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
}

What I can think of is using a buffer where to store chunks coming to you, you know the size via lpNumberOfBytesRead, so on each chunk you check if it contains new line character/s and if it does, you output all the buffered characters till the new line character, then start buffering until you received another chunk with new line characters and so on.

Some pseudo code might look like:

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
}
梦醒灬来后我 2024-10-23 03:06:53

您可以扩展 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;
};

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

You can extend std::basic_streambuf and implement xsputn so it stores data in an internal buffer, and detect newlines or do whatever processing you need. If you want to process only complete lines, upon detection you can push the buffer to a std::queue up to the newline, and erase the respective part from the buffer. You'll need to implement overflow too. For example:

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;
};

NOTE: highly untested code. Let me know if you find a problem, or feel free to edit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文