C++之自定义的output缓冲区
来源:互联网 发布:汉文化复兴 知乎 编辑:程序博客网 时间:2024/05/29 13:21
转自:http://hi.baidu.com/nicker2010/item/661c9bad742dd9a228ce9deb
tream缓冲区是一种I/O缓冲区,其接口由basic_streambuf<>定义
缓冲区的接口主要由三个指针构成。
函数eback(),gptr(),egptr()返回的指针构成了read(即input)缓冲区的界面。
函数pbase(),pptr(),epptr()返回的指针构成了write(即output)缓冲区的界面。
1.pbase()(意思是"put base")是output stream缓冲区的开始位置
2.pptr()(意思是"put pointer")是当前写入位置
3.epptr()(意思是"end put pointer")是是output stream缓冲区的结尾,指向最后一个字符的下一个位置
pbase()和pptr()之间的序列字符(不包括pptr()指向的字符)已被写到相应的输出通道,但是尚未清空(flush)
成员函数sputc()可以写入一个字符:
如果有空位置,字符就复制到该位置,然后pptr()的指针加1
如果缓冲区没有空位置供写入,则会调用overflow()函数将缓冲区的内容发送到相应的通道中
成员函数sputn()可以用来一次写入多个字符。其内部实际上将任务委派给内部函数xsputn()
后者可针对多个字符做更多有效的操作。
通常,同时写入多个字符会比一次写入一个效率高得多,因此可以用sputc()来优化对字符序列的处理
对一个缓冲区写数据时不一定的采取缓冲操作,可以令指令一写入就到达(如cerr),
此时default构造函数会自动将维护write缓冲区的指针设为NULL(0)
没有采取缓冲行为的stream buffer,每个字符到达都会调用overflow()函数
下面就是一个没有采取缓冲行为的自定义stream buffer示例
/**
每一个发送到stream buffer的字符,都转换成大写再以函数putchar()写入
*/
class OutBuf : public std::streambuf
{
protected:
virtual int_type overflow(int_type c)
{
if(c != EOF)
{
c = std::toupper(c,getloc());//getloc()取得与stream对象相关的locale对象
if(putchar(c) == EOF)
return EOF;
}
return c;
}
};
/**
上面这个自定义的stream buffer其实是特别针对char实现的,
因为std::streambuf的定义就是:typedef basic_streambuf<char> streambuf
如果还用到其他字符性别,如wchar_t,则必须运用字符特性来实现这些函数
*/
template <class charT,class traits = std::char_traits<charT> >
class Basic_OutBuf : public std::basic_streambuf<charT,traits>
{
protected:
virtual typename traits::int_type overflow(typename traits::int_type c)
{
if(!traits::eq_int_type(c,traits::eof()))
{
c = std::toupper(c,std::basic_streambuf<charT,traits>::getloc());
if(putchar(c) == EOF)
return traits::eof();
}
return traits::not_eof(c);
}
};
///Basic_OutBuf的简单使用:
typedef Basic_OutBuf<char> outbuf;
typedef Basic_OutBuf<wchar_t> woutbuf;
void testBasicOutBuf()
{ outbuf buffer;
ostream out(&buffer);
out<<"2011 hexadecimal:"<<std::hex<<2011;
}
此方法可以用于对其他任意目标的写入,
例如stream缓冲区可以接受一个文件描述符、一个socket连接、或两个stream缓冲区(用于在对象初始化时同步写入)
若要想目标端改写数据,只要实现overflow()函数,最好也实现xsputn(),这样有助于提升效率
下面定义了一个以文件描述符初始化的stream缓冲区
文件描述符的字符由write()函数写入
extern "C"
{
int write(int fd,const char* buf,int num);
}
class fdOutBuf : public std::streambuf
{
protected:
int fd;
public:
fdOutBuf(int _fd):fd(_fd){}
protected:
virtual int_type overflow(int_type c)
{
if(c != EOF)
{
char z = c;
if(write(fd,&z,1) != 1)
{
return EOF;
}
}
return c;
}
virtual std::streamsize xsputn(const char* s,std::streamsize num)
{
return write(fd,s,num);
}
};
class fdostream : public std::ostream
{
protected:
fdOutBuf buf; ///使用自定义的stream缓冲区
public:
fdostream(int fd):std::ostream(0),buf(fd)
{
rdbuf(&buf);
}
};
void testfdostream()
{
fdostream out(1);/**通常1为标准输出通道*/
out<<"2011 hexadecimal:"<<std::hex<<2011;
}
如果要实现具备缓冲能力的stream缓冲区,
write()函数必须调用setp()初始化
代码如下:
class outputbuf : public std::streambuf
{
protected:
static const int buffersize = 10;
char buffer[buffersize];
public:
outputbuf()
{
setp(buffer,buffer+(buffersize-1));
}
/**保证stream缓冲区被销毁时,缓冲区的数据仍会被写入目标介质中*/
virtual ~outputbuf()
{
sync();
}
protected:
int flushBuffer()/**清空缓冲区*/
{
int num = pptr() - pbase();
if(write(1,buffer,num) != num) /**将缓冲区内的内容输出到标准输出通道*/
return EOF;
pbump(-num); /**当前指针移动到流的来时位置*/
return num;
}
/**只要尚余一个字符空间,就会调用overflow*/
virtual int_type overflow(int_type c)
{
if(c != EOF)
{
*pptr() = c;/**字符写入当前位置*/
pbump(1);
}
if(flushBuffer() == EOF)
{
return EOF;
}
return c;
}
/**造成缓冲区的当前状态和相应的介质同步
唯一需要做的就是清空缓冲区
没有缓冲操作的stream缓冲区,没有必要清空缓冲区,
所有也没必要重载这个虚函数
*/
virtual int sync()
{
if(flushBuffer() == EOF)
{
return -1;
}
return 0;
}
};
C++流这一块感觉比较底层,很多东西都比较陌生。确实比较难哈!
- C++之自定义的output缓冲区
- STL之自定义缓冲区
- PHP Input/Output缓冲区
- 关于C的缓冲区
- c语言的缓冲区
- C语言的缓冲区
- 自定义一个缓冲区的大小
- Output.h && Output.c
- 自定义字节流缓冲区,演示缓冲区的工作原理
- 自定义缓冲区
- C、C++缓冲区的刷新
- 环形缓冲区的c实现
- C、C++缓冲区的刷新
- 有趣的C语言--缓冲区
- c语言缓冲区的理解
- linux系统编程之基础必备(四):C 标准库IO缓冲区和内核缓冲区的区别
- linux系统编程之基础必备(四):C 标准库IO缓冲区和内核缓冲区的区别
- linux系统编程之基础必备(四):C 标准库IO缓冲区和内核缓冲区的区别
- 解决EMF DanglingHREFException的问题
- 自定义basic_streambuf
- 如何集成CKFinder(1)
- 【笔面大全】卡特兰数 Catalan
- Ubuntu下远程访问MySQL数据库
- C++之自定义的output缓冲区
- poj1088
- Windows 7 虚拟串口 VSPD 支持64bit
- html 中<br>和<br/>
- 外国网站
- 为Android交叉编译busybox
- Android-解决AutoCompleteText下拉提示的字体颜色是白色的问题
- wp-主题资源
- 给定一个8*8的方格子,A点到B点的最短路径有多少条?