众所周知,有三个默认I / O流映射到标准库中的预定义对象:
std::istream std::cin
std::ostream std::cout
std::ostream std::cerr
和std::ostream std::clog
但是,从(例如)bash脚本中,您可以创建其他流(3,4,...)。
那么,您是否可以使用描述符3创建额外的输出流并将其绑定到std::ostream custom
对象?如果是这样,怎么样? std::ofstream
没有做到这一点,因为它会创建一个名为“3”的文件,这不是我想要的。
编辑:它不必是可移植的。它适用于POSIX。
答案 0 :(得分:1)
标准中没有提供此功能。好的
执行IOStream,应该有一些额外的,
std::filebuf
的实现特定构造函数,其中
拿一个系统文件描述符(其类型取决于
系统),并从中创建一个filebuf。如果没有,你必须这样做
创建自己的streambuf。这可能或多或少困难,
取决于你需要什么:如果你只需要一个简单的,
单向流(读或写,但不是两者),没有
支持寻求和输入没有代码翻译,它是
相对简单。 (但你仍然需要熟悉
系统级请求,例如read
或write
。)如果您愿意
支持filebuf
所做的一切,更重要
复杂。
我想我会添加一个例子。既然你说bash
,
我想是Unix:
class FdStreambuf : public std::streambuf
{
int myFd;
char buffer[1024];
bool writeBuffer()
{
int len = pptr() - pbase();
return len == 0 || write( myFd, pptr(), len ) == len;
}
protected:
int overflow( int ch )
{
int results = ch == traits::eof() ? 0 : ch;
if ( pbase() != NULL ) {
if ( ! writeBuffer() ) {
results = traits::eof();
}
}
setp( buffer, buffer + sizeof( buffer ) );
sputc( ch );
return ch;
}
int sync()
{
return writeBuffer() ? 0 : -1;
}
public:
FdStreambuf( int fd ) : myFd( fd ) {}
int close()
{
sync();
return ::close( myFd );
}
};
class FdOStream : private FdStreambuf, public std::ostream
{
public:
FdOStream( int fd )
: FdStreambuf( fd )
, std::ostream( this )
{
}
void close()
{
if ( FdStreambuf::close() != 0 ) {
setstate( std::ios_base::badbit );
}
}
};
(我认为这就是必要的,但我有可能 忘记了什么。)
答案 1 :(得分:1)
我合并了Andy和James的回答,这就是我得到的(如果有人需要的话)
#pragma once
#include <ostream>
#include <unistd.h>
namespace util {
class StreamWrapperImpl : public std::ostream {
private:
typedef std::streambuf* OwnedBufPtr;
OwnedBufPtr const buf;
public:
StreamWrapperImpl(OwnedBufPtr buf)
: std::ostream(buf)
, buf(buf)
{}
virtual ~StreamWrapperImpl() {
delete buf;
}
};
template <typename Buf>
class StreamWrapper : public StreamWrapperImpl {
public:
StreamWrapper()
: StreamWrapperImpl(new Buf())
{}
template <typename Arg>
StreamWrapper(Arg arg) // this could use some perfect forwarding in C++11
: StreamWrapperImpl(new Buf(arg))
{}
};
class FdStreamBuf : public std::streambuf {
private:
int fd;
protected:
virtual int_type overflow(int_type c) {
if (c != EOF) {
char const ch = c;
if (write(fd, &ch, 1) != 1)
return EOF;
}
return c;
}
virtual std::streamsize xsputn(char const* s, std::streamsize num) {
return write(fd, s, num);
}
public:
FdStreamBuf(int fd)
: fd(fd)
{
}
};
}