我有以下问题:
我编写了一个简单的解压缩程序,该文件解压缩了.gz文件,该文件由另一进程处理,每行(/ n),为。因此,在shell中,我可以输入:
解压缩文件|程序
这两个程序都是C / C++编码的。
有谁知道我是否以及如何在一个C / C++程序中实现这个“管道”(|),这样我就可以使这种东西成为多线程了……
在我的特殊情况下,保持换行结构完整很重要,这就是为什么我要使用管道。 gz文件太大,无法整体保留在内存中。
最佳答案
通常,在编程中,有一种叫做生成器的东西。在C++中,我们倾向于将它们视为输入迭代器,但所关注的问题仍然相同:就像管道一样,它与拉动式生产有关。
这样,您可以围绕生产者(最好使用输入迭代器的接口(interface))和消费者的思想来重组程序,消费者当时会要求输入一行,生产者会懒惰地提出。
为了获得有关必要接口(interface)的良好指导,我推荐古老的SGI STL网站:此处是InputIterator概念的网站。
对于一个简单的示例,让我们假设我们不必处理解压缩,而只是逐行读取文件:
class LineIterator: public std::iterator<std::input_iterator_tag,
std::string const>
{
public:
// Default Constructible
LineIterator(): stream(nullptr) {}
explicit LineIterator(std::istream& is): stream(&is) { this->advance(); }
// Equality Comparable
friend bool operator==(LineIterator const& left, LineIterator const& right) {
return left.stream == right.stream
and left.buffer == right.buffer
and left.currentLine == right.currentLine;
}
friend bool operator!=(LineIterator const& left, LineIterator const& right) {
return not (left == right);
}
// Trivial Iterator (non mutable)
pointer operator->() const { return ¤tLine; }
reference operator*() const { return currentLine; }
// Input Iterator
LineIterator& operator++() {
this->advance();
return *this;
} // operator++
LineIterator operator++(int) {
LineIterator tmp(*this);
++*this;
return tmp;
} // operator++
private:
void advance() {
// Advance a valid iterator to fetch the next line from the source stream.
static LineIterator const SingularValue;
assert(*this != SingularValue and "Cannot advance singular iterator");
// Note: in real life, I would use std::getline...
// ... but it would not showcase the double-buffering model
// required to solve the OP problem (because of decoding)
// We use double-buffering, so clear current and swap buffers
currentLine.clear();
swap(buffer, currentLine);
// Check if we found some new line or not
size_t const nl = currentLine.find('\n');
// If we found one already, preserve what's after in the buffer
// as we only want to expose one line worth of material.
if (nl != std::string::npos) {
if (nl == currentLine.size()) { return; } // nothing to preserve
buffer.assign(currentLine.begin() + nl + 1, currentLine.end());
currentLine.erase(currentLine.begin() + nl + 1, currentLine.end());
return;
}
// If we did not, then we need to pump more data into the buffer.
if (not stream) { return; } // Nothing to pump...
static size_t const ReadBufferSize = 256;
char input[ReadBufferSize];
while (stream->read(input, ReadBufferSize)) {
if (this->splitBuffer(input, ReadBufferSize)) { break; }
}
// We end up here either if we found a new line or if some read failed.
// If the stream is still good, we successfully found a new line!
if (*stream) { return; }
// Otherwise, the stream is no good any longer (it dried up!)
// but we may still have read some little things from it.
this->splitBuffer(input, stream->gcount());
stream = SingularValue.stream; // stream dried up,
// so reset it to match singular value.
} // advance
bool splitBuffer(char const* input, size_t const size) {
// Split input at the newline character, the first chunk ends
// up in currentLine, the second chunk in buffer.
// Returns true if a newline character was found, false otherwise.
// Check if we finally found a new line
char const* const newLine = std::find(input, input + size, '\n');
// If we did not, copy everything into currentLine and signal it.
if (newLine == input + size) {
currentLine.append(input, size);
return false;
}
// If we did, copy everything up to it (including it) into currentLine
// and then bufferize the rest for the next iteration.
currentLine.append(input, newLine + 1);
buffer.assign(newLine + 1, input + size);
return true;
} // splitBuffer
std::istream* stream;
std::string buffer;
std::string currentLine;
}; // class LineIterator
还是有点大(可能是虫子……),它具有我们需要用STL算法组成的接口(interface),例如:
std::ifstream file("someFile.txt");
std::copy(LineIterator(file), LineIterator(), std::ostream_iterator(std::cout));
它将一次在终端上回显文件一次(demo here)。
现在,您所要做的就是将读取部分(
stream.read
)替换为逐块读取并解压缩:)关于c++ - 在C/C++程序中实现管道,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21206913/