我正在使用win32的ReadFile
来读取子进程的管道。这一次给了我一大块字符和每个块的大小,但它们可能有也可能没有新行。我想逐行处理输出。这样做最简单的方法是什么?
我考虑将每个块附加到string
,最后使用stringstream
逐行处理它,但我想在数据进入时执行此操作。我想诀窍是,我应该如何以及在哪里检测到新的行结束?如果在找不到分隔符时只有streamreader
的{{1}}没有返回任何内容......
答案 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;
};
注意:高度未经测试的代码。如果您发现问题或者随时可以编辑,请告诉我。