c++日志输出

来源:互联网 发布:奥尼尔新秀赛季数据 编辑:程序博客网 时间:2024/06/06 04:05

1、cout经过缓冲后输出,默认情况下是显示器。这是一个被缓冲的输出,是标准输出,并且可以重新定向到文件

2、cerr不经过缓冲而直接输出,一般用于迅速输出出错信息,是标准错误,默认情况下被关联到标准输出流,但它不被缓冲,也就说错误消息可以直接发送到显示器,而无需等到缓冲区或者新的换行符时,才被显示,一般情况下不被重定向,只能在显示器输出

附:

#include <iostream>using namespace std;int main(){cout << "cout" << endl;cerr << "cerr" << endl;system("PAUSE");return 0;}

运行此程序之后,我们在命令行执行如下命令:

假设编译运行后的可执行文件名为cerr.exe,其目录为E:\cpro\cerr\Debug\cerr.exe

在命令行下,切换到这个目录下,执行命令:cerr>test.log

命令行输出如下:

E:\cpro\cerr\Debug>cerr>>test2.log

Cerr(这是在命令行下输出的)

查看test2.log文件,发现里面只有

Cout

日志输出有同步和异步两种:

Log系统如何快速写到磁盘中,关键在于写Log的时候进行顺序写,即每次写Log的大小为4k或者4k的倍数。

同步输出日志:

log有一个4k的buf,如果本次写入的内容数据大小小于buf,那么就把内容拷贝进去buf,然后退出,如果没有再写入日志,则把buf里面的数据写进log文件如果本次写入的内容数据大小大于buf就直接把内容写进log文件。其方法的关键就是减小锁的粒度、合并多次write为一次write以进行顺序写log内容至磁盘上。


---------Log.h

/* * Log.h * *  Created on: 2017年11月16日 *      Author: guojing */#include<pthread.h>#include<string.h>#include<stdio.h>#include<iostream>using namespace std;#ifndef LOG_H_#define LOG_H_#define MaxFileSize 1000 //该文件最大存放量class NetDataLog{struct log_t{FILE *file;char filename[20];pthread_mutex_t mutex;int buf_cursor;char buf[4*1024];log_t();void reset();};public:NetDataLog(){FileCount=0;};~NetDataLog();void init_log(char *filename);int log_write(char *buf,int len);void fileSizeLimit(int datasize);//判断数据是否超过文件剩余大小int getCurrentLogFileSize();//得到当前日志文件的大小private:void fileOffser();//文件名进行偏移log_t log_t_;int FileCount;//文件数};#endif /* LOG_H_ */

--------Log.cpp

/* * Log.cpp * *  Created on: 2017年11月16日 *      Author: guojing */#include"Log.h"//,log有一个4k的buf,如果本次输出的内容能够放到buf里面,那么就把内容拷贝进去,然后退出,否则就调用writev函数把内容写进log文件。//其方法的关键就是减小锁的粒度、合并多次write为一次write以进行顺序写log内容至磁盘上。int NetDataLog::log_write(char *buf,int len){int ret=0;pthread_mutex_lock(&log_t_.mutex);do{int size=log_t_.buf_cursor+len;fileSizeLimit(size);if(size<(int)sizeof(log_t_.buf)){memcpy(log_t_.buf+log_t_.buf_cursor,buf,len);log_t_.buf_cursor=size;break;}fputs(log_t_.buf,log_t_.file);while(size<ret){ret=fputs(buf,log_t_.file);if(ret<0){return ret;}size=size-ret;}log_t_.reset();}while(0);pthread_mutex_unlock(&log_t_.mutex);return ret;}NetDataLog::log_t::log_t(){file=0;buf_cursor=0;}void NetDataLog::log_t::reset(){buf_cursor=0;memset(buf,0,sizeof(buf));}void NetDataLog::init_log(char *filename){strcpy(log_t_.filename,filename);log_t_.file=fopen(log_t_.filename,"w+");log_t_.buf_cursor=0;memset(log_t_.buf,0,sizeof(log_t_.buf));}void NetDataLog::fileSizeLimit(int datasize){    int filesize = getCurrentLogFileSize();    if(datasize>MaxFileSize-filesize)    fileOffser();}int NetDataLog::getCurrentLogFileSize(){int findex=ftell(log_t_.file);//获取当前位置相对于文件首的偏移字节数fseek(log_t_.file,0,SEEK_END);//移动到文件末尾int fsize=ftell(log_t_.file);fseek(log_t_.file,findex,SEEK_SET);//恢复文件位置return fsize;}void NetDataLog::fileOffser(){fclose(log_t_.file);   //关闭当前文件char new_filename[20];memset(new_filename,0,sizeof(new_filename));FileCount++;sprintf(new_filename,"%s%d",log_t_.filename,FileCount);log_t_.file=fopen(new_filename,"w+");memset(log_t_.filename,0,sizeof(log_t_.filename));strcpy(log_t_.filename,new_filename);}NetDataLog::~NetDataLog(){int ret=fputs(log_t_.buf,log_t_.file);fclose(log_t_.file);}


--------Main.cpp

/* * main.cpp * *  Created on: 2017年11月24日 *      Author: guojing */#include<Log.h>int main(){NetDataLog log;log.init_log("./mytest_log");log.log_write("rinige",6);return 0;}


异步输出日志:


所谓的异步输出log就是专门启动一个日志线程,它可以有一个log队列,其他线程作为生产者把内容输出至队列,日志线程就作为消费者从队列中取出log内容,然后把它写到磁盘上。

原创粉丝点击