【c++3】_public.h/cpp,_ooci.h/cpp,_mysql.h/cpp


1._public.h

#ifndef _PUBLIC_H
#define _PUBLIC_H 1
#include "_cmpublic.h"
//全路径文件名,大小,时间的结构体
struct st_fileinfo
{
  char filename[301];
  int  filesize;
  char mtime[21];
};

//1111111111111111111.读取某目录下的全部的文件
class CDir
{
public:
  char m_DirName[301];         // 目录名
  char m_FileName[301];        // 文件名,不包括目录名
  char m_FullFileName[301];    // 文件全名,包括目录名
  int  m_FileSize;             // 文件的大小
  char m_ModifyTime[21];       // 文件最后一次被修改的时间
  char m_CreateTime[21];       // 文件生成的时间
  char m_AccessTime[21];       // 文件最后一次被访问的时间

  int m_uPOS;                 // 已读取m_vFileName容器的位置
  vector<string> m_vFileName;  //  存放OpenDir方法获取到的文件列表

  CDir();

  // 变量初始化
  void initdata();

  // 设置日期时间的格式,支持"yyyy-mm-dd hh24:mi:ss"和"yyyymmddhh24miss"两种格式,缺省是前者
  char m_DateFMT[21];
  void SetDateFMT(const char *in_DateFMT);

  // 打开目录,获取文件名信息,存放于m_vFileName容器中
  // in_DirName,待打开的目录名
  // in_MatchStr,待获取文件名的匹配规则
  // in_MaxCount,获取文件的最大数量
  // bAndChild,是否打开各级子目录
  // bSort,是否对结果集进行排序
  bool OpenDir(const char *in_DirName,const char *in_MatchStr,const unsigned int in_MaxCount=10000,const bool bAndChild=false,bool bSort=false);

  // 这是一个递归函数,用于OpenDir()的调用。
  bool _OpenDir(const char *in_DirName,const char *in_MatchStr,const unsigned int in_MaxCount,const bool bAndChild);

  // 逐个读取目录中的文件信息
  bool ReadDir();

  ~CDir();
};

//111111111111111111112.STRCPY、STRNCPY、STRCAT、STRNCAT四个函数,弥补库函数的缺陷
// 以后可以用这四个函数取代strcpy、strncpy、strcat、strncat
// 函数的第二个参数是第一个参数dest有效长度,即占用内存的字节数-1。
// 该系列函数解决三个问题:1)变量初始化;2)内存溢出;3)修复strncpy的缺陷。
char *STRCPY(char* dest,const size_t destlen,const char* src);
char *STRNCPY(char* dest,const size_t destlen,const char* src,size_t n);
char *STRCAT(char* dest,const size_t destlen,const char* src);
char *STRNCAT(char* dest,const size_t destlen,const char* src,size_t n);

int SNPRINTF(char *str, size_t size, const char *fmt, ...);

// 把整数的时间转换为字符串格式的时间,格式如:"2019-02-08 12:05:08",如果转换成功函数返回0,失败返回-1,函数的声明如下:
int timetostr(const time_t ti,char *strtime);

// 把字符串格式的时间转换为整数的时间,函数的声明如下:
int strtotime(const char *strtime,time_t *ti);

// 从文件文件中读取一行
// strEndStr是一行数据的结束标志,如果为空,则以换行符"\n"为结束标志。
// 本函数不会删除行的结束标志
bool FGETS(const FILE *fp,char *strBuffer,const int ReadSize,const char *strEndStr=0);

//11111111111111111111113.文件操作类声明
class CFile
{
private:
  FILE *m_fp;        // 文件指针
  bool  m_bEnBuffer; // 是否启用缓冲区,true-启用;false-不启用
  char  m_filename[301]; // 文件名
  char  m_filenametmp[301]; // 临时文件名

public:
  CFile();   // 类的构造函数
 ~CFile();   // 类的析构函数

  bool IsOpened();  // 判断文件是否已打开

  // 打开文件,参数与fopen相同,打开成功true,失败返回false          
  bool Open(const char *filename,const char *openmode,bool bEnBuffer=true);
  // 关闭文件指针,并删除文件
  bool CloseAndRemove();

  // 专为改名而创建文件,参数与fopen相同,打开成功true,失败返回false          
  // 函数将会创建filename后加.tmp的临时文件,调用CloseAndRename()后才把临时文件改名为正式文件
  bool OpenForRename(const char *filename,const char *openmode,bool bEnBuffer=true);
  // 关闭文件并改名
  bool CloseAndRename();

  // 调用fprintf向文件写入数据
  void Fprintf(const char *fmt, ... );

  // 调用fgets从文件中读取一行,bDelCRT=true删除换行符,false不删除,缺省为false
  bool Fgets(char *strBuffer,const int ReadSize,bool bDelCRT=false);

  // 从文件文件中读取一行
  // strEndStr是一行数据的结束标志,如果为空,则以换行符"\n"为结束标志。
  // 与Fgets不同,本函数不删除结束标志
  bool FFGETS(char *strBuffer,const int ReadSize,const char *strEndStr=0);

  // 调用fread从文件中读取数据
  size_t Fread(void *ptr,size_t size);

  // 调用fwrite向文件中写数据
  size_t Fwrite(const void *ptr,size_t size);

  // 关闭文件指针,如果存在临时文件,就删除它。
  void Close();
};

//1111111111111111111111111111114.拆分字符串的类
// 字符串的格式为:内容1+分隔字符串+内容2+分隔字符串+内容3
// 如:num~!~name~!~address,分隔符为"~!~"
class CCmdStr
{
public:
  vector<string> m_vCmdStr;  // 存放拆分后的字段内容。

  CCmdStr();

  // 拆分字符串到容器中
  void SplitToCmd(const string in_string,const char *in_sep,const bool bdeletespace=true);

  int CmdCount();

  // 获取字段的值,取每个字段的值inum从0开始
  bool GetValue(const int inum,char   *in_return);
  bool GetValue(const int inum,char   *in_return,const int in_len);
  bool GetValue(const int inum,int    *in_return);
  bool GetValue(const int inum,long   *in_return);
  bool GetValue(const int inum,double *in_return);

  ~CCmdStr();
};

// 删除字符串左边指定的字符
void DeleteLChar(char *in_string,const char in_char);

// 删除字符串右边指定的字符
void DeleteRChar(char *in_string,const char in_char);

// 删除字符串两边指定的字符
void DeleteLRChar(char *in_string,const char in_char);

//11111111111111111115.取操作系统的时间
/*
  out_stime是输出结果
  in_interval是偏移常量,单位是秒
  返回的格式由fmt决定,fmt目前的取值如下,如果需要,可以增加:
  yyyy-mm-dd hh:mi:ss,此格式是缺省格式,长度为19
  yyyymmddhhmiss
  yyyy-mm-dd
  yyyymmdd
  hh:mi:ss
  hhmiss
  hh:mi
  hhmi
  hh
  mi
*/
void LocalTime(char *out_stime,const char *in_fmt=0,const int in_interval=0);

//日志文件操作类
#define MAXLOGFSIZE 100    // 日志文件切换的大小
// 日志文件操作类
class CLogFile
{
public:
  FILE   *m_tracefp;           // 日志文件指针
  char    m_filename[301];     // 日志文件全名
  char    m_openmode[11];      // 日志文件的打开方式
  bool    m_bBackup;           // 日志文件超出MAXLOGFSIZE,是否自动备份
  bool    m_bEnBuffer;         // 写入日志时,是否启用操作系统的缓冲机制

  CLogFile();

  // filename日志文件名
  // openmode打开文件的方式,操作日志文件的权限,同打开文件函数(fopen)使用方法一致,一般采用"a+"
  // bBackup,true-备份,false-不备份,在多进程的服务程序中,如果多个进行共用一个日志文件,bBackup必须为false
  // bEnBuffer:true-启用缓冲区,false-不启用缓冲区,如果启用缓冲区,那么写进日志文件中的内容不会立即写入文件
  // 注意,bEnBuffer参数的值如果设置为true,可能会导致日志文件内容不完整。
  bool Open(const char *in_filename,const char *in_openmode,bool bBackup=true,bool bEnBuffer=false);

  // 如果日志文件大于100M,就备份它
  // 备份后的文件会在源文件名后加上日期时间
  // 注意,在多进程程序中,日志文件不可切换,多线程程序中,日志文件可切换。
  bool BackupLogFile();

  // 写日志文件,它是个可变参数的方法,同printf函数。
  // Write()方法会写入时间,WriteEx()方法不写时间。
  bool Write(const char *fmt,...);
  bool WriteEx(const char *fmt,...);

  // 关闭日志文件
  void Close();

  ~CLogFile();
};

// 关闭全部的信号和输入输出
void CloseIOAndSignal();

// 用某文件或目录的全路径中的目录创建目录,以及该目录下的各级子目录
// pathorfilename 目录名或文件名
// bisfilename true-pathorfilename是文件名,否则是目录名
bool MKDIR(const char *pathorfilename,bool bisfilename=true);

// 删除文件,如果删除失败,会尝试in_times次
bool REMOVE(const char *in_filename,const int in_times=3);

// 把in_srcfilename改名为in_dstfilename,如果改名失败,会尝试in_times次
bool RENAME(const char *in_srcfilename,const char *in_dstfilename,const int in_times=3);

// 把某一个文件复制到另一个文件
bool COPY(const char *srcfilename,const char *dstfilename);

// 调用fopen函数打开文件,如果文件名中包含的目录不存在,就创建目录
FILE *FOPEN(const char *filename,const char *mode);

// 获取文件的大小,返回字节数
int FileSize(const char *in_FullFileName);

// 获取文件的时间,即modtime
void FileMTime(const char *in_FullFileName,char *out_ModTime);

// 更改文件的修改时间属性,mtime指定了时间,格式不限,只要包括了yyyy,mm,dd,hh24,mi,ss即可。
int UTime(const char *filename,const char *mtime);

// 把字符串格式的时间转换为time_t
// stime为输入的时间,格式不限,但一定要包括yyyymmddhh24miss
time_t UTCTime(const char *stime);

// 从一个字符串中提取数字、符号和小数点,并判断是否是一个合法的数
// 如果不合法,将返回空字符串
// bWithSign==true表示包括符号,bWithDOT==true表示包括圆点
void PickNumber(const char *strSrc,char *strDst,const bool bWithSign,const bool bWithDOT);

// 判断字符串中的负号和圆点是否合法
bool JudgeSignDOT(const char *strSrc,const char *strBZ);

/*
  把一个字符串表格的时间加上一个偏移量,得到偏移后的时间
  in_stime是传入的时间,任意格式,但是一定要包括yyyymmddhh24miss,是否有分隔符没有关系。
  把yyyy-mm-dd hh24:mi:ss偏移in_interval秒
  传出的格式由fmt决定,fmt目前的取值如下,如果需要,可以增加:
  yyyy-mm-dd hh24:mi:ss(此格式是缺省格式)
  yyyymmddhh24miss
  yyyymmddhh24miss
  yyyy-mm-dd
  yyyymmdd
  hh24:mi:ss
  hh24miss
  hh24:mi
  hh24mi
  返回值:0-成功,-1-失败。
*/
int AddTime(const char *in_stime,char *out_stime,const int in_interval,const char *in_fmt=0);

//1111111111111111111111116.以下是XML格式字符串的相关操作函数和类
// 操作XMLBuffer的函数
// in_XMLBuffer,XML格式的字符串,如下:
// <filename>/tmp/readme.txt</filename><mtime>2018-01-01 12:20:35</mtime><size>10241</size>
// in_FieldName,字段的标签名
// out_Value,获取内容存放的变量的指针
bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,bool   *out_Value);
bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,int    *out_Value);
bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,unsigned int *out_Value);
bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,long   *out_Value);
bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,unsigned long *out_Value);
bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,double *out_Value);
bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,char   *out_Value,const int in_StrLen=0);

//11111111111111111111111117.判断文件名是否匹配in_MatchStr指定的规则
// in_FileName文件名
// in_MatchStr规则表达式,如"*.txt,*.xml",中间用逗号分隔
bool MatchFileName(const string in_FileName,const string in_MatchStr);

// 把小写转换成大写,忽略不是字母的字符
void ToUpper(char *str);
void ToUpper(string &str);

// 把大写转换成小写,忽略不是字母的字符
void ToLower(char *str);
void ToLower(string &str);

// 字符串替换函数
// 把in_string中的in_str1替换为in_str2
// bLoop是否循环执行替换
// 注意
// 1、如果in_str2比in_str1要长,替换后in_string会变长,所以必须保证in_string有足够的长度, 否则内存会溢出
// 2、如果in_str2中包函了in_str1的内容,且bLoop为true,就会进入死循环,最终导致内存溢出
void UpdateStr(char *in_string,const char *in_str1,const char *in_str2,bool bLoop=true);

//111111111111111111111118.以下是TCP/IP通讯的函数和类
// socket通信的客户端类
class CTcpClient
{
public:
  int  m_sockfd;    // 客户端的socket.
  char m_ip[21];    // 服务端的ip地址。
  int  m_port;      // 与服务端通信的端口。
  bool m_state;     // 与服务端的socket连接状态。
  bool m_btimeout;  // 调用Read和Write方法时,失败的原因是否是超时:true-未超时,false-已超时。
  int  m_buflen;    // 调用Read方法后,接收到的报文的大小,单位:字节。

  CTcpClient();  // 构造函数。

  // 向服务端发起连接请求。
  // ip:服务端的ip地址。
  // port:服务端监听的端口。
  // 返回值:true-成功;false-失败。
  bool ConnectToServer(const char *ip,const int port);

  // 接收服务端发送过来的数据。
  // buffer:接收数据缓冲区的地址,数据的长度存放在m_buflen成员变量中。
  // itimeout:等待数据的超时时间,单位:秒,缺省值是0-无限等待。
  // 返回值:true-成功;false-失败,失败有两种情况:1)等待超时,成员变量m_btimeout的值被设置为true;2)socket连接已不可用。
  bool Read(char *buffer,const int itimeout=0);

  // 向服务端发送数据。
  // buffer:待发送数据缓冲区的地址。
  // ibuflen:待发送数据的大小,单位:字节,缺省值为0,如果发送的是ascii字符串,ibuflen取0,如果是二进制流数据,ibuflen为二进制数据块的大小。
  // 返回值:true-成功;false-失败,如果失败,表示socket连接已不可用。
  bool Write(const char *buffer,const int ibuflen=0);

  // 断开与服务端的连接
  void Close();

  ~CTcpClient();  // 析构函数自动关闭socket,释放资源。
};

// socket通信的服务端类
class CTcpServer
{
private:
  int m_socklen;                    // 结构体struct sockaddr_in的大小。
  struct sockaddr_in m_clientaddr;  // 客户端的地址信息。
  struct sockaddr_in m_servaddr;    // 服务端的地址信息。
public:
  int  m_listenfd;   // 服务端用于监听的socket。
  int  m_connfd;     // 客户端连接上来的socket。
  bool m_btimeout;   // 调用Read和Write方法时,失败的原因是否是超时:true-未超时,false-已超时。
  int  m_buflen;     // 调用Read方法后,接收到的报文的大小,单位:字节。

  CTcpServer();  // 构造函数。

  // 服务端初始化。
  // port:指定服务端用于监听的端口。
  // 返回值:true-成功;false-失败,一般情况下,只要port设置正确,没有被占用,初始化都会成功。
  bool InitServer(const unsigned int port); 

  // 阻塞等待客户端的连接请求。
  // 返回值:true-有新的客户端已连接上来,false-失败,Accept被中断,如果Accept失败,可以重新Accept。
  bool Accept();

  // 获取客户端的ip地址。
  // 返回值:客户端的ip地址,如"192.168.1.100"。
  char *GetIP();

  // 接收客户端发送过来的数据。
  // buffer:接收数据缓冲区的地址,数据的长度存放在m_buflen成员变量中。
  // itimeout:等待数据的超时时间,单位:秒,缺省值是0-无限等待。
  // 返回值:true-成功;false-失败,失败有两种情况:1)等待超时,成员变量m_btimeout的值被设置为true;2)socket连接已不可用。
  bool Read(char *buffer,const int itimeout);

  // 向客户端发送数据。
  // buffer:待发送数据缓冲区的地址。
  // ibuflen:待发送数据的大小,单位:字节,缺省值为0,如果发送的是ascii字符串,ibuflen取0,如果是二进制流数据,ibuflen为二进制数据块的大小。
  // 返回值:true-成功;false-失败,如果失败,表示socket连接已不可用。
  bool Write(const char *buffer,const int ibuflen=0);

  // 关闭监听的socket,即m_listenfd,常用于多进程服务程序的子进程代码中。
  void CloseListen();

  // 关闭客户端的socket,即m_connfd,常用于多进程服务程序的父进程代码中。
  void CloseClient();

  ~CTcpServer();  // 析构函数自动关闭socket,释放资源。
};

// 接收socket的对端发送过来的数据。
// sockfd:可用的socket连接。
// buffer:接收数据缓冲区的地址。
// ibuflen:本次成功接收数据的字节数。
// itimeout:接收等待超时的时间,单位:秒,缺省值是0-无限等待。
// 返回值:true-成功;false-失败,失败有两种情况:1)等待超时;2)socket连接已不可用。
bool TcpRead(const int sockfd,char *buffer,int *ibuflen,const int itimeout=0);

// 向socket的对端发送数据。
// sockfd:可用的socket连接。
// buffer:待发送数据缓冲区的地址。
// ibuflen:待发送数据的字节数,如果发送的是ascii字符串,ibuflen取0,如果是二进制流数据,ibuflen为二进制数据块的大小。
// 返回值:true-成功;false-失败,如果失败,表示socket连接已不可用。
bool TcpWrite(const int sockfd,const char *buffer,const int ibuflen=0);

// 从已经准备好的socket中读取数据。
// sockfd:已经准备好的socket连接。
// buffer:接收数据缓冲区的地址。
// n:本次接收数据的字节数。
// 返回值:成功接收到n字节的数据后返回true,socket连接不可用返回false。
bool Readn(const int sockfd,char *buffer,const size_t n);

// 向已经准备好的socket中写入数据。
// sockfd:已经准备好的socket连接。
// buffer:待发送数据缓冲区的地址。
// n:待发送数据的字节数。
// 返回值:成功发送完n字节的数据后返回true,socket连接不可用返回false。
bool Writen(const int sockfd,const char *buffer,const size_t n);

//111111111111111111119.这是一个精确到微秒的计时器
class CTimer
{
public:
  struct timeval m_start,m_end;

  CTimer();

  // 开始计时
  void Start();

  // 计算已逝去的时间,单位:秒,小数点后面是微秒
  double Elapsed();
};

#endif

2._public.cpp

#include "_public.h"  

int SNPRINTF(char *str, size_t size, const char *fmt, ...)
{
  memset(str,0,size+1);

  va_list arg;

  va_start( arg, fmt );
  vsnprintf( str,size, fmt, arg );
  va_end( arg );
}

char *STRCPY(char* dest,const size_t destlen,const char* src)
{
  memset(dest,0,destlen+1); 

  if (strlen(src)>destlen) strncpy(dest,src,destlen);
  else strcpy(dest,src);

  return dest;
}

char *STRNCPY(char* dest,const size_t destlen,const char* src,size_t n)
{
  memset(dest,0,destlen+1); 

  if (n>destlen) strncpy(dest,src,destlen);
  else strncpy(dest,src,n);

  return dest;
}

char *STRCAT(char* dest,const size_t destlen,const char* src)
{
  memset(dest+strlen(dest),0,destlen-strlen(dest)+1); 
  
  int left=destlen-strlen(dest);

  int len=0;

  if (strlen(src)>left) len=left;
  else len=strlen(src);
  
  strncat(dest,src,len);

  return dest;
}

char *STRNCAT(char* dest,const size_t destlen,const char* src,size_t n)
{
  memset(dest+strlen(dest),0,destlen-strlen(dest)+1); 
  
  int left=destlen-strlen(dest);

  int len=0;

  if (n>left) len=left;
  else len=n;
  
  strncat(dest,src,len);

  return dest;
}


// 把整数的时间转换为字符串格式的时间,格式如:"2019-02-08 12:05:08",如果转换成功函数返回0,失败返回-1,函数的声明如下:
int timetostr(const time_t ti,char *strtime)
{
  struct tm *sttm; 

  if ( (sttm=localtime(&ti))==0 ) return -1;

  sprintf(strtime,"%d-%02d-%02d %02d:%02d:%02d",\
          sttm->tm_year+1900,sttm->tm_mon+1,sttm->tm_mday,sttm->tm_hour,sttm->tm_min,sttm->tm_sec);
  
  return 0;
}

// 把字符串格式的时间转换为整数的时间,函数的声明如下:
int strtotime(const char *strtime,time_t *ti)
{
  char strtmp[11];

  //"2019-02-08 12:05:08"
  struct tm sttm; 

  memset(strtmp,0,sizeof(strtmp));
  strncpy(strtmp,strtime,4);
  sttm.tm_year=atoi(strtmp)-1900;
  
  memset(strtmp,0,sizeof(strtmp));
  strncpy(strtmp,strtime+5,2);
  sttm.tm_mon=atoi(strtmp)-1;
  
  memset(strtmp,0,sizeof(strtmp));
  strncpy(strtmp,strtime+8,2);
  sttm.tm_mday=atoi(strtmp);
  
  memset(strtmp,0,sizeof(strtmp));
  strncpy(strtmp,strtime+11,2);
  sttm.tm_hour=atoi(strtmp);
  
  memset(strtmp,0,sizeof(strtmp));
  strncpy(strtmp,strtime+14,2);
  sttm.tm_min=atoi(strtmp);
  
  memset(strtmp,0,sizeof(strtmp));
  strncpy(strtmp,strtime+17,2);
  sttm.tm_sec=atoi(strtmp);

  *ti=mktime(&sttm);

  return *ti;
}


CFile::CFile()   // 类的构造函数
{
  m_fp=0;
  m_bEnBuffer=true;
  memset(m_filename,0,sizeof(m_filename));
  memset(m_filenametmp,0,sizeof(m_filenametmp));
}

// 关闭文件指针
void CFile::Close() 
{
  if (m_fp==0) return;

  fclose(m_fp);  // 关闭文件指针

  m_fp=0;
  memset(m_filename,0,sizeof(m_filename));

  // 如果存在临时文件,就删除它。
  if (strlen(m_filenametmp)!=0) remove(m_filenametmp);

  memset(m_filenametmp,0,sizeof(m_filenametmp));
}

// 判断文件是否已打开
bool CFile::IsOpened()
{
  if (m_fp==0) return false;

  return true;
}

// 关闭文件指针,并删除文件
bool CFile::CloseAndRemove()
{
  if (m_fp==0) return true;

  fclose(m_fp);  // 关闭文件指针

  m_fp=0;

  if (remove(m_filename) != 0) { memset(m_filename,0,sizeof(m_filename)); return false; }

  memset(m_filename,0,sizeof(m_filename));

  return true;
}

CFile::~CFile()   // 类的析构函数
{
  Close();
}

// 打开文件,参数与FOPEN相同,打开成功true,失败返回false
bool CFile::Open(const char *filename,const char *openmode,bool bEnBuffer)
{
  Close();

  if ( (m_fp=FOPEN(filename,openmode)) == 0 ) return false;

  memset(m_filename,0,sizeof(m_filename));

  strncpy(m_filename,filename,300);

  m_bEnBuffer=bEnBuffer;

  return true;
}

// 专为改名而打开文件,参数与fopen相同,打开成功true,失败返回false
bool CFile::OpenForRename(const char *filename,const char *openmode,bool bEnBuffer)
{
  Close();

  memset(m_filename,0,sizeof(m_filename));
  strncpy(m_filename,filename,300);
  
  memset(m_filenametmp,0,sizeof(m_filenametmp));
  SNPRINTF(m_filenametmp,300,"%s.tmp",m_filename);

  if ( (m_fp=FOPEN(m_filenametmp,openmode)) == 0 ) return false;

  m_bEnBuffer=bEnBuffer;

  return true;
}

// 关闭文件并改名
bool CFile::CloseAndRename()
{
  if (m_fp==0) return false;

  fclose(m_fp);  // 关闭文件指针

  m_fp=0;

  if (rename(m_filenametmp,m_filename) != 0)
  {
    remove(m_filenametmp);
    memset(m_filename,0,sizeof(m_filename));
    memset(m_filenametmp,0,sizeof(m_filenametmp));
    return false;
  }

  memset(m_filename,0,sizeof(m_filename));
  memset(m_filenametmp,0,sizeof(m_filenametmp));

  return true;
}

// 调用fprintf向文件写入数据
void CFile::Fprintf(const char *fmt, ... )
{
  if ( m_fp == 0 ) return;

  va_list arg;

  va_start( arg, fmt );
  vfprintf( m_fp, fmt, arg );
  va_end( arg );

  if ( m_bEnBuffer == false ) fflush(m_fp);
}

// 调用fgets从文件中读取一行,bDelCRT=true删除换行符,false不删除,缺省为false
bool CFile::Fgets(char *strBuffer,const int ReadSize,bool bDelCRT)
{
  if ( m_fp == 0 ) return false;

  memset(strBuffer,0,ReadSize+1);

  if (fgets(strBuffer,ReadSize,m_fp) == 0) return false;

  if (bDelCRT==true)
  {
    DeleteRChar(strBuffer,'\n'); DeleteRChar(strBuffer,'\r');
  }

  return true;
}

// 从文件文件中读取一行
// strEndStr是一行数据的结束标志,如果为空,则以换行符"\n"为结束标志。
// 与Fgets不同,本函数不删除结束标志
bool CFile::FFGETS(char *strBuffer,const int ReadSize,const char *strEndStr)
{
  return FGETS(m_fp,strBuffer,ReadSize,strEndStr);
}

// 调用fread从文件中读取数据。
size_t CFile::Fread(void *ptr, size_t size)
{
  if ( m_fp == 0 ) return -1;

  return fread(ptr,1,size,m_fp);
}

// 调用fwrite向文件中写数据
size_t CFile::Fwrite(const void *ptr, size_t size )
{
  if ( m_fp == 0 ) return -1;

  size_t tt=fwrite(ptr,1,size,m_fp);

  if ( m_bEnBuffer == false ) fflush(m_fp);

  return tt;
}


// 从文件文件中读取一行
// strEndStr是一行数据的结束标志,如果为空,则以换行符"\n"为结束标志。
// 本函数不会删除行的结束标志
bool FGETS(const FILE *fp,char *strBuffer,const int ReadSize,const char *strEndStr)
{
  char strLine[ReadSize+1];

  memset(strLine,0,sizeof(strLine));

  while (true)
  {
    memset(strLine,0,ReadSize+1);

    if (fgets(strLine,ReadSize,(FILE *)fp) == 0) break;

    // 防止strBuffer溢出
    if ( (strlen(strBuffer)+strlen(strLine)) >= (unsigned int)ReadSize ) break;

    strcat(strBuffer,strLine);

    if (strEndStr == 0) return true;

    if (strstr(strLine,strEndStr)!= 0) return true;
  }

  return false;
}


CCmdStr::CCmdStr()
{
  m_vCmdStr.clear();
}

void CCmdStr::SplitToCmd(const string in_string,const char *in_sep,const bool bdeletespace)
{
  // 清除所有的旧数据
  m_vCmdStr.clear();

  int iPOS=0;
  string srcstr,substr;

  srcstr=in_string;

  char str[2048];

  while ( (iPOS=srcstr.find(in_sep)) >= 0)
  {
    substr=srcstr.substr(0,iPOS);

    if (bdeletespace == true)
    {
      memset(str,0,sizeof(str));

      strncpy(str,substr.c_str(),2000);

      DeleteLRChar(str,' ');

      substr=str;
    }

    m_vCmdStr.push_back(substr);

    iPOS=iPOS+strlen(in_sep);

    srcstr=srcstr.substr(iPOS,srcstr.size()-iPOS);

  }

  substr=srcstr;

  if (bdeletespace == true)
  {
    memset(str,0,sizeof(str));

    strncpy(str,substr.c_str(),2000);

    DeleteLRChar(str,' ');

    substr=str;
  }

  m_vCmdStr.push_back(substr);

  return;
}

int CCmdStr::CmdCount()
{
  return m_vCmdStr.size();
}

bool CCmdStr::GetValue(const int inum,char *in_return)
{
  if (inum >= m_vCmdStr.size()) return false;

  strcpy(in_return,m_vCmdStr[inum].c_str());

  return true;
}

bool CCmdStr::GetValue(const int inum,char *in_return,const int in_len)
{
  memset(in_return,0,in_len+1);

  if (inum >= m_vCmdStr.size()) return false;

  if (m_vCmdStr[inum].length() > (unsigned int)in_len)
  {
    strncpy(in_return,m_vCmdStr[inum].c_str(),in_len);
  }
  else
  {
    strcpy(in_return,m_vCmdStr[inum].c_str());
  }

  return true;
}

bool CCmdStr::GetValue(const int inum,int *in_return)
{
  (*in_return) = 0;

  if (inum >= m_vCmdStr.size()) return false;

  (*in_return) = atoi(m_vCmdStr[inum].c_str());

  return true;
}

bool CCmdStr::GetValue(const int inum,long *in_return)
{
  (*in_return) = 0;

  if (inum >= m_vCmdStr.size()) return false;

  (*in_return) = atol(m_vCmdStr[inum].c_str());

  return true;
}

bool CCmdStr::GetValue(const int inum,double *in_return)
{
  (*in_return) = 0;

  if (inum >= m_vCmdStr.size()) return false;

  (*in_return) = (double)atof(m_vCmdStr[inum].c_str());

  return true;
}

CCmdStr::~CCmdStr()
{
  m_vCmdStr.clear();
}

/* 删除字符串左边指定的字符 */
void DeleteLChar(char *in_string,const char in_char)
{
  if (in_string == 0) return;

  if (strlen(in_string) == 0) return;

  char strTemp[strlen(in_string)+1];

  int iTemp=0;

  memset(strTemp,0,sizeof(strTemp));
  strcpy(strTemp,in_string);

  while ( strTemp[iTemp] == in_char )  iTemp++;

  memset(in_string,0,strlen(in_string)+1);

  strcpy(in_string,strTemp+iTemp);

  return;
}

/* 删除字符串右边指定的字符 */
void DeleteRChar(char *in_string,const char in_char)
{
  if (in_string == 0) return;

  int istrlen = strlen(in_string);

  while (istrlen>0)
  {
    if (in_string[istrlen-1] != in_char) break;

    in_string[istrlen-1]=0;

    istrlen--;
  }
}

/* 删除字符串两边指定的字符 */
void DeleteLRChar(char *in_string,const char in_char)
{
  DeleteLChar(in_string,in_char);
  DeleteRChar(in_string,in_char);
}


/*
   取操作系统的时间
   out_stime是输出结果
   in_interval是偏移常量,单位是秒
   返回的格式由fmt决定,fmt目前的取值如下,如果需要,可以增加:
   yyyy-mm-dd hh24:mi:ss,此格式是缺省格式
   yyyymmddhh24miss
   yyyy-mm-dd
   yyyymmdd
   hh24:mi:ss
   hh24miss
   hh24:mi
   hh24mi
   hh24
   mi
*/
void LocalTime(char *out_stime,const char *in_fmt,const int in_interval)
{
  if (in_fmt == 0) memset(out_stime,0,19+1);
  else memset(out_stime,0,strlen(in_fmt)+1);  
  
  time_t  timer;
  struct tm nowtimer;

  time( &timer ); timer=timer+in_interval;
  nowtimer = *localtime ( &timer ); nowtimer.tm_mon++;

  if (in_fmt==0)
  {
    snprintf(out_stime,20,"%04u-%02u-%02u %02u:%02u:%02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour,
                    nowtimer.tm_min,nowtimer.tm_sec);
    return;
  }

  if (strcmp(in_fmt,"yyyy-mm-dd hh24:mi:ss") == 0)
  {
    snprintf(out_stime,20,"%04u-%02u-%02u %02u:%02u:%02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour,
                    nowtimer.tm_min,nowtimer.tm_sec);
    return;
  }

  if (strcmp(in_fmt,"yyyy-mm-dd hh24:mi") == 0)
  {
    snprintf(out_stime,17,"%04u-%02u-%02u %02u:%02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour,
                    nowtimer.tm_min);
    return;
  }

  if (strcmp(in_fmt,"yyyy-mm-dd hh24") == 0)
  {
    snprintf(out_stime,14,"%04u-%02u-%02u %02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour);
    return;
  }

  if (strcmp(in_fmt,"yyyy-mm-dd") == 0)
  {
    snprintf(out_stime,11,"%04u-%02u-%02u",nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday); return;
  }

  if (strcmp(in_fmt,"yyyy-mm") == 0)
  {
    snprintf(out_stime,8,"%04u-%02u",nowtimer.tm_year+1900,nowtimer.tm_mon); return;
  }

  if (strcmp(in_fmt,"yyyymmddhh24miss") == 0)
  {
    snprintf(out_stime,15,"%04u%02u%02u%02u%02u%02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour,
                    nowtimer.tm_min,nowtimer.tm_sec);
    return;
  }

  if (strcmp(in_fmt,"yyyymmddhh24mi") == 0)
  {
    snprintf(out_stime,13,"%04u%02u%02u%02u%02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour,
                    nowtimer.tm_min);
    return;
  }

  if (strcmp(in_fmt,"yyyymmddhh24") == 0)
  {
    snprintf(out_stime,11,"%04u%02u%02u%02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour);
    return;
  }

  if (strcmp(in_fmt,"yyyymmdd") == 0)
  {
    snprintf(out_stime,9,"%04u%02u%02u",nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday); return;
  }

  if (strcmp(in_fmt,"hh24miss") == 0)
  {
    snprintf(out_stime,7,"%02u%02u%02u",nowtimer.tm_hour,nowtimer.tm_min,nowtimer.tm_sec); return;
  }

  if (strcmp(in_fmt,"hh24mi") == 0)
  {
    snprintf(out_stime,5,"%02u%02u",nowtimer.tm_hour,nowtimer.tm_min); return;
  }

  if (strcmp(in_fmt,"hh24") == 0)
  {
    snprintf(out_stime,3,"%02u",nowtimer.tm_hour); return;
  }

  if (strcmp(in_fmt,"mi") == 0)
  {
    snprintf(out_stime,3,"%02u",nowtimer.tm_min); return;
  }
}


CLogFile::CLogFile()
{
  m_tracefp = 0;
  memset(m_filename,0,sizeof(m_filename));
  memset(m_openmode,0,sizeof(m_openmode));
  m_bBackup=true;
  m_bEnBuffer=false;  //日志文件一般不启用缓冲区,可以立即看到
}

CLogFile::~CLogFile()
{
  Close();
}

void CLogFile::Close()
{
  if (m_tracefp != 0)
  {
    fclose(m_tracefp); m_tracefp=0;
  }
}

// filename日志文件名
// openmode打开文件的方式,操作日志文件的权限,同打开文件函数(FOPEN)使用方法一致
// bBackup,true-备份,false-不备份,在多进程的服务程序中,如果多个进行共用一个日志文件,bBackup必须为false
// bEnBuffer:true-启用缓冲区,false-不启用缓冲区,如果启用缓冲区,那么写进日志文件中的内容不会立即写入文件是
bool CLogFile::Open(const char *in_filename,const char *in_openmode,bool bBackup,bool bEnBuffer)
{
  if (m_tracefp != 0) { fclose(m_tracefp); m_tracefp=0; }

  m_bEnBuffer=bEnBuffer;

  memset(m_filename,0,sizeof(m_filename));
  strcpy(m_filename,in_filename);

  memset(m_openmode,0,sizeof(m_openmode));
  strcpy(m_openmode,in_openmode);

  if ((m_tracefp=FOPEN(m_filename,m_openmode)) == NULL) return false;

  m_bBackup=bBackup;

  return true;
}

// 如果日志文件大于MAXLOGFSIZE,就备份它
bool CLogFile::BackupLogFile()
{
  // 不备份
  if (m_bBackup == false) return true;

  if (m_tracefp == 0) return true;

  fseek(m_tracefp,0L,2);  //定位到文件最后,我们打开日志文件用a或a+这种方式,一打开任何时候文件指针都是在文件最后,这行代码可省

  if (ftell(m_tracefp) > MAXLOGFSIZE*1024*1024)  // 看看文件有多大
  {
    fclose(m_tracefp); m_tracefp=0;

    char strLocalTime[21];
    memset(strLocalTime,0,sizeof(strLocalTime));
    LocalTime(strLocalTime,"yyyymmddhhmiss");

    char bak_filename[301];
    memset(bak_filename,0,sizeof(bak_filename));
    snprintf(bak_filename,300,"%s.%s",m_filename,strLocalTime);
    rename(m_filename,bak_filename);
printf("rename %s m_filename ok\n",bak_filename);
    if ((m_tracefp=FOPEN(m_filename,m_openmode)) == NULL) return false;
  }

  return true;
}

bool CLogFile::Write(const char *fmt,...)
{
  if (BackupLogFile() == false) return false;

  char strtime[20]; LocalTime(strtime);

  va_list ap;

  va_start(ap,fmt);

  if (m_tracefp == 0)  // m_tracefp日志文件指针
  {
    fprintf(stdout,"%s ",strtime); // stdout:C语言缺省的标准输出,strtime:输出时间
    vfprintf(stdout,fmt,ap);  // ap:输出内容
    if (m_bEnBuffer==false) fflush(stdout);
  }
  else
  {
    fprintf(m_tracefp,"%s ",strtime);
    vfprintf(m_tracefp,fmt,ap);
    if (m_bEnBuffer==false) fflush(m_tracefp);
  }

  va_end(ap);

  return true;
}

bool CLogFile::WriteEx(const char *fmt,...)
{
  va_list ap;
  va_start(ap,fmt);

  if (m_tracefp == 0)
  {
    vfprintf(stdout,fmt,ap);
    if (m_bEnBuffer==false) fflush(stdout);
  }
  else
  {
    vfprintf(m_tracefp,fmt,ap);
    if (m_bEnBuffer==false) fflush(m_tracefp);
  }

  va_end(ap);

  return true;
}

// 关闭全部的信号和输入输出
void CloseIOAndSignal()
{
  int ii=0;

  for (ii=0;ii<50;ii++)
  {
    signal(ii,SIG_IGN); close(ii);
  }
}

// 用某文件或目录的全路径中的目录创建目录,以级该目录下的各级子目录
bool MKDIR(const char *filename,bool bisfilename)
{
  // 检查目录是否存在,如果不存在,逐级创建子目录
  char strPathName[301];

  for (int ii=1; ii<strlen(filename);ii++)
  {
    if (filename[ii] != '/') continue;

    memset(strPathName,0,sizeof(strPathName));
    strncpy(strPathName,filename,ii);

    if (access(strPathName,F_OK) == 0) continue;

    if (mkdir(strPathName,00755) != 0) return false;
  }

  if (bisfilename==false)
  {
    if (access(filename,F_OK) != 0)
    {
      if (mkdir(filename,00755) != 0) return false;
    }
  }

  return true;
}

// 调用fopen函数打开文件,如果文件名中包含的目录不存在,就创建目录
FILE *FOPEN(const char *filename,const char *mode)
{
  if (MKDIR(filename) == false) return NULL;

  return fopen(filename,mode);
}

// 获取文件的大小,返回字节数
int FileSize(const char *in_FullFileName)
{
  struct stat st_filestat;

  if (stat(in_FullFileName,&st_filestat) < 0) return -1;

  return st_filestat.st_size;
}

// 更改文件的修改时间属性
int UTime(const char *filename,const char *mtime)
{
  struct utimbuf stutimbuf;

  stutimbuf.actime=stutimbuf.modtime=UTCTime(mtime);

  return utime(filename,&stutimbuf);
}

// 把字符串格式的时间转换为time_t
// stime为输入的时间,格式不限,但一定要包括yyyymmddhh24miss
time_t UTCTime(const char *stime)
{
  char strtime[21],yyyy[5],mm[3],dd[3],hh[3],mi[3],ss[3];
  memset(strtime,0,sizeof(strtime));
  memset(yyyy,0,sizeof(yyyy));
  memset(mm,0,sizeof(mm));
  memset(dd,0,sizeof(dd));
  memset(hh,0,sizeof(hh));
  memset(mi,0,sizeof(mi));
  memset(ss,0,sizeof(ss));

  PickNumber(stime,strtime,false,false);

  if (strlen(strtime) != 14) return -1;

  strncpy(yyyy,strtime,4);
  strncpy(mm,strtime+4,2);
  strncpy(dd,strtime+6,2);
  strncpy(hh,strtime+8,2);
  strncpy(mi,strtime+10,2);
  strncpy(ss,strtime+12,2);

  struct tm time_str;

  time_str.tm_year = atoi(yyyy) - 1900;
  time_str.tm_mon = atoi(mm) - 1;
  time_str.tm_mday = atoi(dd);
  time_str.tm_hour = atoi(hh);
  time_str.tm_min = atoi(mi);
  time_str.tm_sec = atoi(ss);
  time_str.tm_isdst = 0;

  return mktime(&time_str);
}

// 从一个字符串中提取数字,bWithSign==true表示包括负号,bWithDOT==true表示包括圆点
void PickNumber(const char *strSrc,char *strDst,const bool bWithSign,const bool bWithDOT)
{
  char strtemp[1024];
  memset(strtemp,0,sizeof(strtemp));
  strncpy(strtemp,strSrc,1000);
  DeleteLRChar(strtemp,' ');

  // 为了防止strSrc和strDst为同一变量的情况,所以strDst不能初始化

  // 判断字符串中的负号是否合法
  if ( (bWithSign==true) && (JudgeSignDOT(strtemp,"-") == false) )
  {
    strcpy(strDst,""); return;
  }

  // 判断字符串中的正号是否合法
  if ( (bWithSign==true) && (JudgeSignDOT(strtemp,"+") == false) )
  {
    strcpy(strDst,""); return;
  }

  // 判断字符串中的圆点是否合法
  if ( (bWithDOT==true) && (JudgeSignDOT(strtemp,".") == false) )
  {
    strcpy(strDst,""); return;
  }

  int iPosSrc,iPosDst,iLen;
  iPosSrc=iPosDst=iLen=0;

  iLen=strlen(strtemp);

  for (iPosSrc=0;iPosSrc<iLen;iPosSrc++)
  {
    if ( (bWithSign==true) && (strtemp[iPosSrc] == '+') )
    {
      strDst[iPosDst++]=strtemp[iPosSrc]; continue;
    }

    if ( (bWithSign==true) && (strtemp[iPosSrc] == '-') )
    {
      strDst[iPosDst++]=strtemp[iPosSrc]; continue;
    }

    if ( (bWithDOT==true) && (strtemp[iPosSrc] == '.') )
    {
      strDst[iPosDst++]=strtemp[iPosSrc]; continue;
    }

    if (isdigit(strtemp[iPosSrc])) strDst[iPosDst++]=strtemp[iPosSrc];
  }

  strDst[iPosDst]=0;

  return;
}

// 判断字符串中的负号和圆点是否合法
bool JudgeSignDOT(const char *strSrc,const char *strBZ)
{
  char *pos=0;
  pos=(char *)strstr(strSrc,strBZ);

  // 如果没有包括待搜索的字符串,就返回true
  if (pos == 0) return true;

  // 如果strlen(pos)==1,表示结果中只有符号,没有其它字符,返回false
  if (strlen(pos)==1) return false;

  // 如果待搜索的字符串是+号,就一定要是第一个字符
  if ( (strcmp(strBZ,"+") == 0) && (strncmp(strSrc,"+",1) != 0) ) return false;

  // 如果待搜索的字符串是-号,就一定要是第一个字符
  if ( (strcmp(strBZ,"-") == 0) && (strncmp(strSrc,"-",1) != 0) ) return false;

  // 如果包括多个待搜索的字符串,就返回false
  if (strstr(pos+1,strBZ) > 0) return false;

  return true;
}

/*
  把一个字符串表格的时间加上一个偏移量,得到偏移后的时间
  in_stime是传入的时间,任意格式,但是一定要包括yyyymmddhh24miss,是否有分隔符没有关系。
  把yyyy-mm-dd hh24:mi:ss偏移in_interval秒
  传出的格式由fmt决定,fmt目前的取值如下,如果需要,可以增加:
  yyyy-mm-dd hh24:mi:ss(此格式是缺省格式)
  yyyymmddhh24miss
  yyyymmddhh24miss
  yyyy-mm-dd
  yyyymmdd
  hh24:mi:ss
  hh24miss
  hh24:mi
  hh24mi
  返回值:0-成功,-1-失败。
*/
int AddTime(const char *in_stime,char *out_stime,const int in_interval,const char *in_fmt)
{
  time_t  timer;
  struct tm nowtimer;

  timer=UTCTime(in_stime)+in_interval;

  nowtimer = *localtime ( &timer ); nowtimer.tm_mon++;

  // 为了防止in_stime和out_stime为同一变量的情况,所以out_stime在此处初始化,代码不可提前
  out_stime[0]=0;

  if (in_fmt==0)
  {
    snprintf(out_stime,20,"%04u-%02u-%02u %02u:%02u:%02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour,
                    nowtimer.tm_min,nowtimer.tm_sec); return 0;
  }

  if (strcmp(in_fmt,"yyyy-mm-dd hh24:mi:ss") == 0)
  {
    snprintf(out_stime,20,"%04u-%02u-%02u %02u:%02u:%02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour,
                    nowtimer.tm_min,nowtimer.tm_sec); return 0;
  }

  if (strcmp(in_fmt,"yyyymmddhh24miss") == 0)
  {
    snprintf(out_stime,15,"%04u%02u%02u%02u%02u%02u",nowtimer.tm_year+1900,
                    nowtimer.tm_mon,nowtimer.tm_mday,nowtimer.tm_hour,
                    nowtimer.tm_min,nowtimer.tm_sec); return 0;
  }

  if (strcmp(in_fmt,"yyyy-mm-dd") == 0)
  {
    snprintf(out_stime,11,"%04u-%02u-%02u",nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday); return 0;
  }
  if (strcmp(in_fmt,"yyyymmdd") == 0)
  {
    snprintf(out_stime,9,"%04u%02u%02u",nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday); return 0;
  }

  if (strcmp(in_fmt,"hh24:mi:ss") == 0)
  {
    snprintf(out_stime,9,"%02u:%02u:%02u",nowtimer.tm_hour,nowtimer.tm_min,nowtimer.tm_sec); return 0;
  }

  if (strcmp(in_fmt,"hh24:mi") == 0)
  {
    snprintf(out_stime,9,"%02u:%02u",nowtimer.tm_hour,nowtimer.tm_min); return 0;
  }


  if (strcmp(in_fmt,"hh24mi") == 0)
  {
    snprintf(out_stime,7,"%02u%02u",nowtimer.tm_hour,nowtimer.tm_min); return 0;
  }

  return -1;
}

// 获取文件的时间,即modtime
void FileMTime(const char *in_FullFileName,char *out_ModTime)
{
  struct tm nowtimer;
  struct stat st_filestat;

  stat(in_FullFileName,&st_filestat);

  nowtimer = *localtime(&st_filestat.st_mtime);
  nowtimer.tm_mon++;

  snprintf(out_ModTime,15,"%04u%02u%02u%02u%02u%02u",\
             nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday,\
             nowtimer.tm_hour,nowtimer.tm_min,nowtimer.tm_sec);
}

// 操作XMLBuffer的函数
// in_XMLBuffer,XML格式的字符串
// in_FieldName,字段的标签名
// out_Value,获取内容存放的变量的指针
bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,char *out_Value,const int in_Len)
{
  strcpy(out_Value,"");

  char *start=NULL,*end=NULL;
  char m_SFieldName[51],m_EFieldName[51];

  int m_NameLen = strlen(in_FieldName);
  memset(m_SFieldName,0,sizeof(m_SFieldName));
  memset(m_EFieldName,0,sizeof(m_EFieldName));

  snprintf(m_SFieldName,50,"<%s>",in_FieldName);
  snprintf(m_EFieldName,50,"</%s>",in_FieldName);

  start=0; end=0;

  start = (char *)strstr(in_XMLBuffer,m_SFieldName);

  if (start != 0)
  {
    end   = (char *)strstr(start,m_EFieldName);
  }

  if ((start==0) || (end == 0))
  {
    return false;
  }

  int   m_ValueLen = end - start - m_NameLen - 2 + 1 ;

  if ( ((m_ValueLen-1) <= in_Len) || (in_Len == 0) )
  {
    strncpy(out_Value,start+m_NameLen+2,m_ValueLen-1); out_Value[m_ValueLen-1]=0;
  }
  else
  {
    strncpy(out_Value,start+m_NameLen+2,in_Len); out_Value[in_Len]=0;
  }

  DeleteLRChar(out_Value,' ');

  return true;
}

bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,bool *out_Value)
{
  (*out_Value) = false;

  char strTemp[51];

  memset(strTemp,0,sizeof(strTemp));

  if (GetXMLBuffer(in_XMLBuffer,in_FieldName,strTemp,10) == true)
  {
    if ( (strcmp(strTemp,"true")==0) || (strcmp(strTemp,"true")==0) ) (*out_Value)=true; return true;
  }

  return false;
}

bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,int *out_Value)
{
  (*out_Value) = 0;

  char strTemp[51];

  memset(strTemp,0,sizeof(strTemp));

  if (GetXMLBuffer(in_XMLBuffer,in_FieldName,strTemp,50) == true)
  {
    (*out_Value) = atoi(strTemp); return true;
  }

  return false;
}

bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,unsigned int *out_Value)
{
  (*out_Value) = 0;

  char strTemp[51];

  memset(strTemp,0,sizeof(strTemp));

  if (GetXMLBuffer(in_XMLBuffer,in_FieldName,strTemp,50) == true)
  {
    (*out_Value) = (unsigned int)atoi(strTemp); return true;
  }

  return false;
}

bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,long *out_Value)
{
  (*out_Value) = 0;

  char strTemp[51];

  memset(strTemp,0,sizeof(strTemp));

  if (GetXMLBuffer(in_XMLBuffer,in_FieldName,strTemp,50) == true)
  {
    (*out_Value) = atol(strTemp); return true;
  }

  return false;
}

bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,unsigned long *out_Value)
{
  (*out_Value) = 0;

  char strTemp[51];

  memset(strTemp,0,sizeof(strTemp));

  if (GetXMLBuffer(in_XMLBuffer,in_FieldName,strTemp,50) == true)
  {
    (*out_Value) = (unsigned long)atol(strTemp); return true;
  }

  return false;
}

bool GetXMLBuffer(const char *in_XMLBuffer,const char *in_FieldName,double *out_Value)
{
  (*out_Value) = 0;

  char strTemp[51];

  memset(strTemp,0,sizeof(strTemp));

  if (GetXMLBuffer(in_XMLBuffer,in_FieldName,strTemp,50) == true)
  {
    (*out_Value) = atof(strTemp); return true;
  }

  return false;
}

// 判断文件名是否和MatchFileName匹配,如果不匹配,返回失败
bool MatchFileName(const string in_FileName,const string in_MatchStr)
{
  // 如果用于比较的字符是空的,返回false
  if (in_MatchStr.size() == 0) return false;

  // 如果被比较的字符串是“*”,返回true
  if (in_MatchStr == "*") return true;

  // 处理文件名匹配规则中的时间匹配dd-nn.mm
  char strTemp[2049];
  memset(strTemp,0,sizeof(strTemp));
  strncpy(strTemp,in_MatchStr.c_str(),2000);

  int ii,jj;
  int  iPOS1,iPOS2;
  CCmdStr CmdStr,CmdSubStr;

  string strFileName,strMatchStr;

  strFileName=in_FileName;
  strMatchStr=strTemp;

  // 把字符串都转换成大写后再来比较
  ToUpper(strFileName);
  ToUpper(strMatchStr);

  CmdStr.SplitToCmd(strMatchStr,",");

  for (ii=0;ii<CmdStr.CmdCount();ii++)
  {
    // 如果为空,就一定要跳过,否则就会被配上
    if (CmdStr.m_vCmdStr[ii].empty() == true) continue;

    iPOS1=iPOS2=0;
    CmdSubStr.SplitToCmd(CmdStr.m_vCmdStr[ii],"*");

    for (jj=0;jj<CmdSubStr.CmdCount();jj++)
    {
      // 如果是文件名的首部
      if (jj == 0)
      {
        if (strncmp(strFileName.c_str(),CmdSubStr.m_vCmdStr[jj].c_str(),CmdSubStr.m_vCmdStr[jj].size()) != 0) break;
      }

      // 如果是文件名的尾部
      if (jj == CmdSubStr.CmdCount()-1)
      {
        if (strcmp(strFileName.c_str()+strFileName.size()-CmdSubStr.m_vCmdStr[jj].size(),CmdSubStr.m_vCmdStr[jj].c_str()) != 0) break;
      }

      iPOS2=strFileName.find(CmdSubStr.m_vCmdStr[jj],iPOS1);

      if (iPOS2 < 0) break;

      iPOS1=iPOS2+CmdSubStr.m_vCmdStr[jj].size();
    }

    if (jj==CmdSubStr.CmdCount()) return true;
  }

  return false;
}

void ToUpper(char *str)
{
  if (str == 0) return;

  if (strlen(str) == 0) return;

  int istrlen=strlen(str);

  for (int ii=0;ii<istrlen;ii++)
  {
    if ( (str[ii] >= 97) && (str[ii] <= 122) ) str[ii]=str[ii] - 32;
  }
}

void ToUpper(string &str)
{
  if (str.empty()) return;

  char strtemp[str.size()+1];

  memset(strtemp,0,sizeof(strtemp));
  strcpy(strtemp,str.c_str());

  ToUpper(strtemp);

  str=strtemp;

  return;
}

void ToLower(char *str)
{
  if (str == 0) return;

  if (strlen(str) == 0) return;

  int istrlen=strlen(str);

  for (int ii=0;ii<istrlen;ii++)
  {
    if ( (str[ii] >= 65) && (str[ii] <= 90) ) str[ii]=str[ii] + 32;
  }
}

void ToLower(string &str)
{
  if (str.empty()) return;

  char strtemp[str.size()+1];

  memset(strtemp,0,sizeof(strtemp));
  strcpy(strtemp,str.c_str());

  ToLower(strtemp);

  str=strtemp;

  return;
}


CDir::CDir()
{
  m_uPOS=0;

  memset(m_DateFMT,0,sizeof(m_DateFMT));
  strcpy(m_DateFMT,"yyyy-mm-dd hh24:mi:ss");

  m_vFileName.clear();

  initdata();
}

void CDir::initdata()
{
  memset(m_DirName,0,sizeof(m_DirName));
  memset(m_FileName,0,sizeof(m_FileName));
  memset(m_FullFileName,0,sizeof(m_FullFileName));
  m_FileSize=0;
  memset(m_CreateTime,0,sizeof(m_CreateTime));
  memset(m_ModifyTime,0,sizeof(m_ModifyTime));
  memset(m_AccessTime,0,sizeof(m_AccessTime));
}

// 设置日期时间的格式,支持"yyyy-mm-dd hh24:mi:ss"和"yyyymmddhh24miss"两种格式,缺省是前者
void CDir::SetDateFMT(const char *in_DateFMT)
{
  memset(m_DateFMT,0,sizeof(m_DateFMT));
  strcpy(m_DateFMT,in_DateFMT);
}

// 打开目录,获取文件名信息,存放于m_vFileName容器中
// in_dirname,待打开的目录名
// in_MatchStr,待获取文件名的匹配规则
// in_MaxCount,获取文件的最大数量
// bAndChild,是否打开各级子目录
// bSort,是否对结果时行排序
bool CDir::OpenDir(const char *in_DirName,const char *in_MatchStr,const unsigned int in_MaxCount,const bool bAndChild,bool bSort)
{
  m_uPOS=0;
  m_vFileName.clear();

  // 如果目录不存在,就创建该目录
  if (MKDIR(in_DirName,false) == false) return false;

  bool bRet=_OpenDir(in_DirName,in_MatchStr,in_MaxCount,bAndChild);

  if (bSort==true)
  {
    sort(m_vFileName.begin(), m_vFileName.end());
  }

  return bRet;
}

// 打开目录,这是个递归函数
bool CDir::_OpenDir(const char *in_DirName,const char *in_MatchStr,const unsigned int in_MaxCount,const bool bAndChild)
{
  DIR *dir;

  if ( (dir=opendir(in_DirName)) == NULL ) return false;

  char strTempFileName[1024];

  struct dirent *st_fileinfo;
  struct stat st_filestat;

  while ((st_fileinfo=readdir(dir)) != NULL)
  {
    // 以"."打头的文件不处理
    if (st_fileinfo->d_name[0]=='.') continue;
        
    memset(strTempFileName,0,sizeof(strTempFileName));

    snprintf(strTempFileName,300,"%s//%s",in_DirName,st_fileinfo->d_name);

    UpdateStr(strTempFileName,"//","/");

    stat(strTempFileName,&st_filestat);

    // 判断是否是目录
    if (S_ISDIR(st_filestat.st_mode))
    {
      if (bAndChild == true)
      {
        if (_OpenDir(strTempFileName,in_MatchStr,in_MaxCount,bAndChild) == false) 
        {
          closedir(dir); return false;
        }
      }
    }
    else
    {
      if (MatchFileName(st_fileinfo->d_name,in_MatchStr) == false) continue;

      m_vFileName.push_back(strTempFileName);

      if ( m_vFileName.size()>in_MaxCount ) break;
    }
  }

  closedir(dir);

  return true;
}

bool CDir::ReadDir()
{
  initdata();

  // 如果已读完,清空容器
  if (m_uPOS >= m_vFileName.size()) 
  {
    m_uPOS=0; m_vFileName.clear(); return false;
  }

  int pos=0;

  pos=m_vFileName[m_uPOS].find_last_of("/");

  // 目录名
  memset(m_DirName,0,sizeof(m_DirName));
  strcpy(m_DirName,m_vFileName[m_uPOS].substr(0,pos).c_str());

  // 文件名
  memset(m_FileName,0,sizeof(m_FileName));
  strcpy(m_FileName,m_vFileName[m_uPOS].substr(pos+1,m_vFileName[m_uPOS].size()-pos-1).c_str());

  // 文件全名,包括路径
  snprintf(m_FullFileName,300,"%s",m_vFileName[m_uPOS].c_str());

  struct stat st_filestat;

  stat(m_FullFileName,&st_filestat);

  m_FileSize=st_filestat.st_size;

  struct tm nowtimer;

  if (strcmp(m_DateFMT,"yyyy-mm-dd hh24:mi:ss") == 0)
  {
    nowtimer = *localtime(&st_filestat.st_mtime); nowtimer.tm_mon++;
    snprintf(m_ModifyTime,20,"%04u-%02u-%02u %02u:%02u:%02u",\
             nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday,\
             nowtimer.tm_hour,nowtimer.tm_min,nowtimer.tm_sec);

    nowtimer = *localtime(&st_filestat.st_ctime); nowtimer.tm_mon++;
    snprintf(m_CreateTime,20,"%04u-%02u-%02u %02u:%02u:%02u",\
             nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday,\
             nowtimer.tm_hour,nowtimer.tm_min,nowtimer.tm_sec);

    nowtimer = *localtime(&st_filestat.st_atime); nowtimer.tm_mon++;
    snprintf(m_AccessTime,20,"%04u-%02u-%02u %02u:%02u:%02u",\
             nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday,\
             nowtimer.tm_hour,nowtimer.tm_min,nowtimer.tm_sec);
  }

  if (strcmp(m_DateFMT,"yyyymmddhh24miss") == 0)
  {
    nowtimer = *localtime(&st_filestat.st_mtime); nowtimer.tm_mon++;
    snprintf(m_ModifyTime,20,"%04u%02u%02u%02u%02u%02u",\
             nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday,\
             nowtimer.tm_hour,nowtimer.tm_min,nowtimer.tm_sec);

    nowtimer = *localtime(&st_filestat.st_ctime); nowtimer.tm_mon++;
    snprintf(m_CreateTime,20,"%04u%02u%02u%02u%02u%02u",\
             nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday,\
             nowtimer.tm_hour,nowtimer.tm_min,nowtimer.tm_sec);

    nowtimer = *localtime(&st_filestat.st_atime); nowtimer.tm_mon++;
    snprintf(m_AccessTime,20,"%04u%02u%02u%02u%02u%02u",\
             nowtimer.tm_year+1900,nowtimer.tm_mon,nowtimer.tm_mday,\
             nowtimer.tm_hour,nowtimer.tm_min,nowtimer.tm_sec);
  }

  m_uPOS++;

  return true;
}

CDir::~CDir()
{
  m_vFileName.clear();

  // m_vDirName.clear();
}

// 把字符串中的某字符串用另一个字符串代替
void UpdateStr(char *in_string,const char *in_str1,const char *in_str2,bool bLoop)
{
  if (in_string == 0) return;

  if (strlen(in_string) == 0) return;

  char strTemp[2048];

  char *strStart=in_string;

  char *strPos=0;

  while (true)
  {
    if (strlen(in_string) >2000) break;

    if (bLoop == true)
    {
      strPos=strstr(in_string,in_str1);
    }
    else
    {
      strPos=strstr(strStart,in_str1);
    }

    if (strPos == 0) break;

    memset(strTemp,0,sizeof(strTemp));
    strncpy(strTemp,in_string,strPos-in_string);
    strcat(strTemp,in_str2);
    strcat(strTemp,strPos+strlen(in_str1));
    strcpy(in_string,strTemp);

    strStart=strPos+strlen(in_str2);
  }
}

// 删除文件,如果删除失败,会尝试in_times次
bool REMOVE(const char *in_filename,const int in_times)
{
  // 如果文件不存在,直接返回失败
  if (access(in_filename,R_OK) != 0) return false;

  for (int ii=0;ii<in_times;ii++)
  {
    if (remove(in_filename) == 0) return true;

    usleep(100000);
  }

  return false;
}

// 把in_srcfilename改名为in_dstfilename,如果改名失败,会尝试in_times次
bool RENAME(const char *in_srcfilename,const char *in_dstfilename,const int in_times)
{
  // 如果文件不存在,直接返回失败
  if (access(in_srcfilename,R_OK) != 0) return false;

  if (MKDIR(in_dstfilename) == false) return false;

  for (int ii=0;ii<in_times;ii++)
  {
    if (rename(in_srcfilename,in_dstfilename) == 0) return true;

    usleep(100000);
  }

  return false;
}

CTcpClient::CTcpClient()
{
  m_sockfd=-1;
  memset(m_ip,0,sizeof(m_ip));
  m_port=0;
  m_btimeout=false;
}

bool CTcpClient::ConnectToServer(const char *ip,const int port)
{
  if (m_sockfd != -1) { close(m_sockfd); m_sockfd = -1; }

  strcpy(m_ip,ip);
  m_port=port;

  struct hostent* h;
  struct sockaddr_in servaddr;

  if ( (m_sockfd = socket(AF_INET,SOCK_STREAM,0) ) < 0) return false;

  if ( !(h = gethostbyname(m_ip)) )
  {
    close(m_sockfd);  m_sockfd = -1; return false;
  }

  memset(&servaddr,0,sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_port = htons(m_port);  // 指定服务端的通讯端口
  memcpy(&servaddr.sin_addr,h->h_addr,h->h_length);

  if (connect(m_sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr)) != 0)
  {
    close(m_sockfd);  m_sockfd = -1; return false;
  }

  return true;
}

bool CTcpClient::Read(char *buffer,const int itimeout)
{
  if (m_sockfd == -1) return false;

  if (itimeout>0)
  {
    fd_set tmpfd;

    FD_ZERO(&tmpfd);
    FD_SET(m_sockfd,&tmpfd);

    struct timeval timeout;
    timeout.tv_sec = itimeout; timeout.tv_usec = 0;

    m_btimeout = false;

    int i;
    if ( (i = select(m_sockfd+1,&tmpfd,0,0,&timeout)) <= 0 )
    {
      if (i==0) m_btimeout = true;
      return false;
    }
  }

  m_buflen = 0;
  return (TcpRead(m_sockfd,buffer,&m_buflen));
}

bool CTcpClient::Write(const char *buffer,const int ibuflen)
{
  if (m_sockfd == -1) return false;

  fd_set tmpfd;

  FD_ZERO(&tmpfd);
  FD_SET(m_sockfd,&tmpfd);

  struct timeval timeout;
  timeout.tv_sec = 5; timeout.tv_usec = 0;
  
  m_btimeout = false;

  int i;
  if ( (i=select(m_sockfd+1,0,&tmpfd,0,&timeout)) <= 0 )
  {
    if (i==0) m_btimeout = true;
    return false;
  }

  int ilen=ibuflen;

  if (ibuflen==0) ilen=strlen(buffer);

  return(TcpWrite(m_sockfd,buffer,ilen));
}

void CTcpClient::Close()
{
  if (m_sockfd > 0) close(m_sockfd); 

  m_sockfd=-1;
  memset(m_ip,0,sizeof(m_ip));
  m_port=0;
  m_btimeout=false;
}

CTcpClient::~CTcpClient()
{
  Close();
}

CTcpServer::CTcpServer()
{
  m_listenfd=-1;
  m_connfd=-1;
  m_socklen=0;
  m_btimeout=false;
}

bool CTcpServer::InitServer(const unsigned int port)
{
  if (m_listenfd > 0) { close(m_listenfd); m_listenfd=-1; }

  m_listenfd = socket(AF_INET,SOCK_STREAM,0);

  // WINDOWS平台如下
  //char b_opt='1';
  //setsockopt(m_listenfd,SOL_SOCKET,SO_REUSEADDR,&b_opt,sizeof(b_opt));
  //setsockopt(m_listenfd,SOL_SOCKET,SO_KEEPALIVE,&b_opt,sizeof(b_opt));

  // Linux如下
  int opt = 1; unsigned int len = sizeof(opt);
  setsockopt(m_listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,len);
  setsockopt(m_listenfd,SOL_SOCKET,SO_KEEPALIVE,&opt,len);

  memset(&m_servaddr,0,sizeof(m_servaddr));
  m_servaddr.sin_family = AF_INET;
  m_servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  m_servaddr.sin_port = htons(port);
  if (bind(m_listenfd,(struct sockaddr *)&m_servaddr,sizeof(m_servaddr)) != 0 )
  {
    CloseListen(); return false;
  }

  if (listen(m_listenfd,5) != 0 )
  {
    CloseListen(); return false;
  }

  m_socklen = sizeof(struct sockaddr_in);

  return true;
}

bool CTcpServer::Accept()
{
  if (m_listenfd == -1) return false;

  if ((m_connfd=accept(m_listenfd,(struct sockaddr *)&m_clientaddr,(socklen_t*)&m_socklen)) < 0)
      return false;

  return true;
}

char *CTcpServer::GetIP()
{
  return(inet_ntoa(m_clientaddr.sin_addr));
}

bool CTcpServer::Read(char *buffer,const int itimeout)
{
  if (m_connfd == -1) return false;

  if (itimeout>0)
  {
    fd_set tmpfd;

    FD_ZERO(&tmpfd);
    FD_SET(m_connfd,&tmpfd);

    struct timeval timeout;
    timeout.tv_sec = itimeout; timeout.tv_usec = 0;

    m_btimeout = false;

    int i;
    if ( (i = select(m_connfd+1,&tmpfd,0,0,&timeout)) <= 0 )
    {
      if (i==0) m_btimeout = true;
      return false;
    }
  }

  m_buflen = 0;
  return(TcpRead(m_connfd,buffer,&m_buflen));
}

bool CTcpServer::Write(const char *buffer,const int ibuflen)
{
  if (m_connfd == -1) return false;

  fd_set tmpfd;

  FD_ZERO(&tmpfd);
  FD_SET(m_connfd,&tmpfd);

  struct timeval timeout;
  timeout.tv_sec = 5; timeout.tv_usec = 0;
  
  m_btimeout = false;

  int i;
  if ( (i=select(m_connfd+1,0,&tmpfd,0,&timeout)) <= 0 )
  {
    if (i==0) m_btimeout = true;
    return false;
  }

  int ilen = ibuflen;
  if (ilen==0) strlen(buffer);

  return(TcpWrite(m_connfd,buffer,ilen));
}

void CTcpServer::CloseListen()
{
  if (m_listenfd > 0)
  {
    close(m_listenfd); m_listenfd=-1;
  }
}

void CTcpServer::CloseClient()
{
  if (m_connfd > 0)
  {
    close(m_connfd); m_connfd=-1; 
  }
}

CTcpServer::~CTcpServer()
{
  CloseListen(); CloseClient();
}

bool TcpRead(const int sockfd,char *buffer,int *ibuflen,const int itimeout)
{
  if (sockfd == -1) return false;

  if (itimeout > 0)
  {
    fd_set tmpfd;

    FD_ZERO(&tmpfd);
    FD_SET(sockfd,&tmpfd);

    struct timeval timeout;
    timeout.tv_sec = itimeout; timeout.tv_usec = 0;

    int i;
    if ( (i = select(sockfd+1,&tmpfd,0,0,&timeout)) <= 0 ) return false;
  }

  (*ibuflen) = 0;

  if (Readn(sockfd,(char*)ibuflen,4) == false) return false;

  if (Readn(sockfd,buffer,(*ibuflen)) == false) return false;

  return true;
}

bool TcpWrite(const int sockfd,const char *buffer,const int ibuflen)
{
  if (sockfd == -1) return false;

  fd_set tmpfd;

  FD_ZERO(&tmpfd);
  FD_SET(sockfd,&tmpfd);

  struct timeval timeout;
  timeout.tv_sec = 5; timeout.tv_usec = 0;

  if ( select(sockfd+1,0,&tmpfd,0,&timeout) <= 0 ) return false;
  
  int ilen=0;

  // 如果长度为0,就采用字符串的长度
  if (ibuflen==0) ilen=strlen(buffer);
  else ilen=ibuflen;

  char strTBuffer[ilen+4];
  memset(strTBuffer,0,sizeof(strTBuffer));
  memcpy(strTBuffer,&ilen,4);
  memcpy(strTBuffer+4,buffer,ilen);
  
  if (Writen(sockfd,strTBuffer,ilen+4) == false) return false;

  return true;
}

bool Readn(const int sockfd,char *buffer,const size_t n)
{
  int nLeft,nread,idx;

  nLeft = n;
  idx = 0;

  while(nLeft > 0)
  {
    if ( (nread = recv(sockfd,buffer + idx,nLeft,0)) <= 0) return false;

    idx += nread;
    nLeft -= nread;
  }

  return true;
}

bool Writen(const int sockfd,const char *buffer,const size_t n)
{
  int nLeft,idx,nwritten;
  nLeft = n;  
  idx = 0;
  while(nLeft > 0 )
  {    
    if ( (nwritten = send(sockfd, buffer + idx,nLeft,0)) <= 0) return false;      
    
    nLeft -= nwritten;
    idx += nwritten;
  }

  return true;
}

// 把文件通过sockfd发送给对端
bool SendFile(int sockfd,struct st_fileinfo *stfileinfo,CLogFile *logfile)
{
  char strSendBuffer[301],strRecvBuffer[301];
  memset(strSendBuffer,0,sizeof(strSendBuffer));

  snprintf(strSendBuffer,300,"<filename>%s</filename><filesize>%d</filesize><mtime>%s</mtime>",stfileinfo->filename,stfileinfo->filesize,stfileinfo->mtime);

  if (TcpWrite(sockfd,strSendBuffer) == false)
  {
    if (logfile!=0) logfile->Write("SendFile TcpWrite() failed.\n"); 
    return false;
  }

  int  bytes=0;
  int  total_bytes=0;
  int  onread=0;
  char buffer[1000];

  FILE *fp=0;

  if ( (fp=FOPEN(stfileinfo->filename,"rb")) == 0 )
  {
    if (logfile!=0) logfile->Write("SendFile FOPEN(%s) failed.\n",stfileinfo->filename); 
    return false;
  }

  while (true)
  {
    memset(buffer,0,sizeof(buffer));

    if ((stfileinfo->filesize-total_bytes) > 1000) onread=1000;
    else onread=stfileinfo->filesize-total_bytes;

    bytes=fread(buffer,1,onread,fp);

    if (bytes > 0)
    {
      if (Writen(sockfd,buffer,bytes) == false)
      {
        if (logfile!=0) logfile->Write("SendFile Writen() failed.\n"); 
        fclose(fp); fp=0; return false;
      }
    }

    total_bytes = total_bytes + bytes;

    if ((int)total_bytes == stfileinfo->filesize) break;
  }

  fclose(fp);

  // 接收对端返回的确认报文
  int buflen=0;
  memset(strRecvBuffer,0,sizeof(strRecvBuffer));
  if (TcpRead(sockfd,strRecvBuffer,&buflen)==false)
  {
    if (logfile!=0) logfile->Write("SendFile TcpRead() failed.\n"); 
    return false;
  }

  if (strcmp(strRecvBuffer,"ok")!=0) return false;

  return true;
}

// 接收通过socdfd发送过来的文件
bool RecvFile(int sockfd,struct st_fileinfo *stfileinfo,CLogFile *logfile)
{
  char strSendBuffer[301],strRecvBuffer[301];

  char strfilenametmp[301]; memset(strfilenametmp,0,sizeof(strfilenametmp));
  sprintf(strfilenametmp,"%s.tmp",stfileinfo->filename);

  FILE *fp=0;

  if ( (fp=FOPEN(strfilenametmp,"wb")) ==0)     // FOPEN可创建目录
  {
    if (logfile!=0) logfile->Write("RecvFile FOPEN %s failed.\n",strfilenametmp); 
    return false;
  }

  int  total_bytes=0;
  int  onread=0;
  char buffer[1000];

  while (true)
  {
    memset(buffer,0,sizeof(buffer));

    if ((stfileinfo->filesize-total_bytes) > 1000) onread=1000;
    else onread=stfileinfo->filesize-total_bytes;

    if (Readn(sockfd,buffer,onread) == false)
    {
      if (logfile!=0) logfile->Write("RecvFile Readn() failed.\n"); 
      fclose(fp); fp=0; return false;
    }

    fwrite(buffer,1,onread,fp);

    total_bytes = total_bytes + onread;

    if ((int)total_bytes == stfileinfo->filesize) break;
  }

  fclose(fp);

  // 重置文件的时间
  UTime(strfilenametmp,stfileinfo->mtime);

  memset(strSendBuffer,0,sizeof(strSendBuffer));
  if (RENAME(strfilenametmp,stfileinfo->filename)==true) strcpy(strSendBuffer,"ok");
  else strcpy(strSendBuffer,"failed");

  // 向对端返回响应内容
  if (TcpWrite(sockfd,strSendBuffer)==false)
  {
    if (logfile!=0) logfile->Write("RecvFile TcpWrite() failed.\n"); 
    return false;
  }

  if (strcmp(strSendBuffer,"ok") != 0) return false;

  return true;
}

// 把某一个文件复制到另一个文件
bool COPY(const char *srcfilename,const char *dstfilename)
{
  if (MKDIR(dstfilename) == false) return false;

  char strdstfilenametmp[301];
  memset(strdstfilenametmp,0,sizeof(strdstfilenametmp));
  snprintf(strdstfilenametmp,300,"%s.tmp",dstfilename);

  int  srcfd,dstfd;

  srcfd=dstfd=-1;

  int iFileSize=FileSize(srcfilename);

  int  bytes=0;
  int  total_bytes=0;
  int  onread=0;
  char buffer[5000];

  if ( (srcfd=open(srcfilename,O_RDONLY)) < 0 ) return false;

  if ( (dstfd=open(strdstfilenametmp,O_WRONLY|O_CREAT|O_TRUNC,S_IWUSR|S_IRUSR|S_IXUSR)) < 0) { close(srcfd); return false; }

  while (true)
  {
    memset(buffer,0,sizeof(buffer));

    if ((iFileSize-total_bytes) > 5000) onread=5000;
    else onread=iFileSize-total_bytes;

    bytes=read(srcfd,buffer,onread);

    if (bytes > 0) write(dstfd,buffer,bytes);

    total_bytes = total_bytes + bytes;

    if (total_bytes == iFileSize) break;
  }

  close(srcfd);

  close(dstfd);

  // 更改文件的修改时间属性
  char strmtime[21];
  memset(strmtime,0,sizeof(strmtime));
  FileMTime(srcfilename,strmtime);
  UTime(strdstfilenametmp,strmtime);

  if (RENAME(strdstfilenametmp,dstfilename) == false) { REMOVE(strdstfilenametmp); return false; }

  return true;
}

CTimer::CTimer()
{
  memset(&m_start,0,sizeof(struct timeval));
  memset(&m_end,0,sizeof(struct timeval));

  // 开始计时
  Start();
}

// 开始计时
void CTimer::Start()
{
  gettimeofday( &m_start, NULL );
}

// 计算已逝去的时间,单位:秒,小数点后面是微秒
double CTimer::Elapsed()
{
  gettimeofday( &m_end, NULL );
  double dstart,dend;
  dstart=dend=0;
  char strtemp[51];
  memset(strtemp,0,sizeof(strtemp));
  snprintf(strtemp,30,"%ld.%ld",m_start.tv_sec,m_start.tv_usec);
  dstart=atof(strtemp);

  memset(strtemp,0,sizeof(strtemp));
  snprintf(strtemp,30,"%ld.%ld",m_end.tv_sec,m_end.tv_usec);
  dend=atof(strtemp);

  // 重新开始计时
  Start();
  return dend-dstart;
}

3._cmpublic.h

#ifndef _cmpublic_H
#define _cmpublic_H

#include <stdio.h>
#include <utime.h>
//#include <curl/curl.h>
#include <string.h>
#include <strings.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <limits.h>
#include <time.h>
#include <math.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <netdb.h>
#include <locale.h>
#include <dirent.h>
#include <termios.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iconv.h>
//#include<openssl/md5.h>

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <list>
#include <vector>
#include <deque>
#include <algorithm>

//#include <boost/thread/thread.hpp>
//#include <boost/shared_ptr.hpp>
//#include <boost/signal.hpp>

// 定义C++标准模板库的命名空间
using namespace std;

// 以下是定义布尔数据类型的几个宏,在有的UNIX中,不一定支持布尔类型,
// 所以在这里自定义
#ifndef BOOL
  #define BOOL unsigned char 
#endif

#ifndef bool
  #define bool unsigned char 
#endif

#ifndef TRUE
  #define TRUE 1
#endif

#ifndef true
  #define true 1
#endif

#ifndef FALSE
  #define FALSE 0
#endif

#ifndef false
  #define false 0
#endif

#ifndef INT
  #define INT long
#endif

#ifndef UINT
  #define UINT unsigned long
#endif

#ifndef UCHAR
  #define UCHAR unsigned long
#endif

#endif

4._ooci.h

//connection和sqlstatement类,CDA_DEF结构体
#ifndef __OOCI_H
#define __OOCI_H

// C/C++库常用头文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

// oracle数据库接口库头文件,必须在装有oracle数据库主机运行
#include <oci.h>

// OCI登录环境
struct LOGINENV
{
  char user[32];     // 数据库的用户名
  char pass[32];     // 数据库的密码
  char tnsname[51];  // 数据库的tnsname,在ORACLE_HOME/network/admin/tnsnames.ora中配置

  OCIEnv *envhp; // 环境变量的句柄
};

// OCI上下文
struct OCI_CXT
{
  OCISvcCtx  *svchp;
  OCIError   *errhp;
  OCIEnv     *envhp;   // 环境变量的句柄
};

// 语句
struct OCI_HANDLE
{
  OCISvcCtx  *svchp;  // 服务器上下文的句柄引用context句柄
  OCIStmt    *smthp;

  OCIBind    *bindhp;
  OCIDefine  *defhp;

  OCIError   *errhp;  // 错误句柄引用context句柄

  OCIEnv     *envhp; // 环境变量的句柄 引用context句柄
};

//11111111111111111111.OCI执行的结果
struct CDA_DEF
{
  int      rc;             // 执行结果
  unsigned long rpc;       // 执行SQL语句后,影响记录的行数
  char     message[2048];  // 执行SQL语句如果失败,存放错误信息
};

int oci_init(LOGINENV *env);
int oci_close(LOGINENV *env); 
int oci_context_create(LOGINENV *env,OCI_CXT *cxt);
int oci_context_close(OCI_CXT *cxt);

int oci_stmt_create(OCI_CXT *cxt,OCI_HANDLE *handle);
int oci_stmt_close(OCI_HANDLE *handle);

//1111111111111111112.数据库连接池类
class connection
{
private:
  // 服务器环境句柄
  LOGINENV m_env;

public:
  // 服务器上下文
  OCI_CXT m_cxt;

  // 连接状态,0-未连接,1-已连接
  int m_state;

  // 自动提交标志,0-关闭自动提交;1-开启自动提交
  int m_autocommitopt; 

  // 数据库种类,固定取值为oracle
  char m_dbtype[21];

  // 用于存放connection操作数据库的错误或最后一次执行SQL语句的结果
  CDA_DEF m_cda;

  connection();

 ~connection();

  // 设置字符集,如果客户端的字符集与数据库的不一致,就会出现乱码。
  // 本方法要在connecttodb()之前调用。
  void character(char *charset);

  // 连接数据库,connstr的格式为:username/password@tnsname,autocommitopt:0-关闭自动提交,1-启用自动提交
  int connecttodb(char *connstr,char *charset,int autocommitopt=0);

  // 从connstr中解析username,password,tnsname
  void setdbopt(char *connstr);

  // 断开与数据库的连接
  int  disconnect();

  // 提交事务
  int  commit(); 

  // 回滚事务
  int  rollback();

  // 获取错误信息
  void err_report();
};

//1111111111111111113.SQL语言数据操作类
class sqlstatement
{
public:
  // 与数据库连接池的状态,0-未绑定,1-已绑定
  int m_state;    

  // 语句句柄
  OCI_HANDLE m_handle;

  connection *m_conn;

  // SQL语句
  char m_sql[10240];

  // 执行结果
  CDA_DEF m_cda;

  int m_sqltype;  // 待执行的SQL语句的类型,0-查询语句;1-非查询语句

  // 自动提交标志,0-关闭自动提交;1-开启自动提交
  int m_autocommitopt; 

  sqlstatement();
  sqlstatement(connection *conn);

 ~sqlstatement();

  // 设定数据库连接池
  int  connect(connection *conn); 

  // 断开与数据库连接池的连接
  int  disconnect();

  // 分析SQL语句,支持存储过程,采用立刻分析的方式,即时返回分析结果
  int  prepare(const char *fmt,...);

  // 绑定输入变量的地址
  int  bindin(unsigned int position,int    *value);
  int  bindin(unsigned int position,long   *value);
  int  bindin(unsigned int position,unsigned int  *value);
  int  bindin(unsigned int position,unsigned long *value);
  int  bindin(unsigned int position,float *value);
  int  bindin(unsigned int position,double *value);
  int  bindin(unsigned int position,char   *value,unsigned int len);

  // 绑定输出变量的地址
  int  bindout(unsigned int position,int    *value);
  int  bindout(unsigned int position,long   *value);
  int  bindout(unsigned int position,unsigned int  *value);
  int  bindout(unsigned int position,unsigned long *value);
  int  bindout(unsigned int position,float *value);
  int  bindout(unsigned int position,double *value);
  int  bindout(unsigned int position,char   *value,unsigned int len);

  // 执行SQL语句
  int  execute();
  
  // 如果SQL语句不需要输入和输出变量,可以直接执行。
  int  execute(const char *fmt,...);

  // 取下一条记录,只有当SQL语句是查询语句时才有意义 
  int  next();

  // 错误报告
  void err_report();

  // 指向LOB字段的指针,在执行execute后,用bindblob或bindclob绑定,再用next获取指针
  OCILobLocator *m_lob;

  // 初始化lob指针,在sqlstatement::connect()中调用
  int  alloclob();
  
  // 释放lob指针,在sqlstatement::disconnect()中调用
  void freelob();

  // 绑定lob指针
  int  bindblob();
  int  bindclob();

  // 以下两个函数都是把文件中的内容写入LOB字段,第二个函数是被第一个函数调用的
  int  filetolob(char *filename);
  int  filetolob(FILE *fp);

  // 把LOB字段中的内容写入文件
  int  lobtofile(char *filename);
  int  lobtofile(FILE *fp);
};
#endif 

5._ooci.cpp

// 如果是windows平台,要用以下行,否则会报以下错误
// _ooci.cpp(845) : fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?
// #include "stdafx.h"

#include "_ooci.h"

/*
OCI_SUCCESS                0  // maps to SQL_SUCCESS of SAG CLI  函数执行成功
OCI_SUCCESS_WITH_INFO      1  // maps to SQL_SUCCESS_WITH_INFO   执行成功,但有诊断消息返回,
                              // 可能是警告信息,但是,在测试的时候,我还从未见
                              // 识到OCI_SUCCESS_WITH_INFO是怎么回事
OCI_RESERVED_FOR_INT_USE 200  // reserved 
OCI_NO_DATA              100  // maps to SQL_NO_DATA 函数执行完成,但没有其他数据 
OCI_ERROR                 -1  // maps to SQL_ERROR 函数执行错误 
OCI_INVALID_HANDLE        -2  // maps to SQL_INVALID_HANDLE 传递给函数的参数为无效句柄,
                              // 或传回的句柄无效 
OCI_NEED_DATA             99  // maps to SQL_NEED_DATA 需要应用程序提供运行时刻的数据
OCI_STILL_EXECUTING    -3123  // OCI would block error 服务环境建立在非阻塞模式,
                              // OCI函数调用正在执行中

OCI_CONTINUE          -24200  // Continue with the body of the OCI function 
                              // 说明回调函数需要OCI库恢复其正常的处理操作 
OCI_ROWCBK_DONE       -24201  // done with user row callback 
*/

int oci_init(LOGINENV *env)
{
  //初始化Oracle 环境变量
  int  oci_ret;

  oci_ret = OCIEnvCreate(&env->envhp,OCI_DEFAULT,NULL,NULL,NULL,NULL,0,NULL);

  if ( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO ) 
  {
    oci_close(env); return -1;
  }

  return 0;
} 

int oci_close(LOGINENV *env)
{
  int oci_ret;

  // 释放Oracle 环境变量
  oci_ret=OCIHandleFree(env->envhp,OCI_HTYPE_ENV);

  env->envhp = 0;

  return oci_ret;
}

int oci_context_create(LOGINENV *env,OCI_CXT *cxt )
{
  // 创建数据库连接的上下文对象,连接服务器,认证并建立会话

  if (env->envhp == 0) return -1;

  int oci_ret;
    
  oci_ret = OCIHandleAlloc(env->envhp,(dvoid**)&cxt->errhp,OCI_HTYPE_ERROR,(size_t) 0,NULL);

  if ( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO ) 
  {
    oci_context_close(cxt); return -1;
  }

  // 登录
  oci_ret = OCILogon(env->envhp,cxt->errhp,&cxt->svchp,(OraText*)env->user,strlen(env->user),
                     (OraText*)env->pass,strlen(env->pass),(OraText*)env->tnsname,strlen(env->tnsname));

  if( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO )
  {
    oci_context_close(cxt); return -1;
  }

  cxt->envhp = env->envhp;

  return 0;    
}

int oci_context_close(OCI_CXT *cxt)
{
  // 关闭数据库连接的上下文

  int oci_ret;
    
  oci_ret = OCILogoff(cxt->svchp,cxt->errhp);

  oci_ret = OCIHandleFree(cxt->svchp,OCI_HTYPE_SVCCTX);

  oci_ret = OCIHandleFree(cxt->errhp, OCI_HTYPE_ERROR);

  cxt->svchp=0;

  cxt->errhp=0;

  return oci_ret;
}

int oci_stmt_create(OCI_CXT *cxt,OCI_HANDLE *handle )
{
  //创建语句
  int  oci_ret;
    
  oci_ret = OCIHandleAlloc( cxt->envhp, (dvoid**)&handle->smthp, OCI_HTYPE_STMT,(size_t)0, NULL);

  if( oci_ret == OCI_SUCCESS || oci_ret == OCI_SUCCESS_WITH_INFO )
  {
    handle->svchp  = cxt->svchp;
    handle->errhp  = cxt->errhp;
    handle->envhp = cxt->envhp;

    oci_ret = OCI_SUCCESS;
  }

  return oci_ret;
}

int oci_stmt_close(OCI_HANDLE *handle)
{
  // 关闭语句
  int oci_ret=0;

  oci_ret = OCIHandleFree(handle->smthp,OCI_HTYPE_STMT);

  return oci_ret;
}

connection::connection()
{ 
  m_state = 0; 

  memset(&m_cxt,0,sizeof(OCI_CXT));
  memset(&m_env,0,sizeof(LOGINENV));

  memset(&m_cda,0,sizeof(m_cda));

  m_cda.rc=-1;
  strncpy(m_cda.message,"database not open.",128);

  // 数据库种类
  memset(m_dbtype,0,sizeof(m_dbtype));
  strcpy(m_dbtype,"oracle");
}

connection::~connection()
{
  disconnect();
}

// 从connstr中解析username,password,tnsname
void connection::setdbopt(char *connstr)
{
  char strtemp[201];

  memset(strtemp,0,sizeof(strtemp));

  strncpy(strtemp,connstr,128);

  char *pos=0;

  // tnsname
  pos = strstr(strtemp,"@");
  if (pos > 0) 
  {
    strncpy(m_env.tnsname,pos+1,50); pos[0]=0;
  }

  // password
  pos = strstr(strtemp,"/");
  if (pos > 0) 
  {
    strncpy(m_env.pass,pos+1,30); pos[0]=0;
  }

  // username
  strncpy(m_env.user,strtemp,30); 
}


// 设置字符集,如果客户端的字符集与数据库的不一致,就会出现乱码。
void connection::character(char *charset)
{
  // UNIX平台是采用setenv函数
  setenv("NLS_LANG",charset,1);

  // windows是采用putenv,如下
  /*
  char str[100];
  memset(str,0,sizeof(str));
  _snprintf(str,50,"NLS_LANG=%s",charset);
  putenv(str);
  */
}

int connection::connecttodb(char *connstr,char *charset,int autocommitopt)
{
  // 如果已连接上数据库,就不再连接
  // 所以,如果想重连数据库,必须显示的调用disconnect()方法后才能重连
  if (m_state == 1) return 0;

  // 设置字符集
  character(charset);

  // 设置日期字段的输出格式
  
  // UNIX平台是采用setenv函数
  // setenv("NLS_DATE_FORMAT","yyyy-mm-dd hh24:mi:ss",1);
  
  // windows是采用putenv,如下
  // putenv("NLS_DATE_FORMAT=yyyy-mm-dd hh24:mi:ss");
  
  
  // 从connstr中解析username,password,tnsname
  setdbopt(connstr);

  memset(&m_cda,0,sizeof(m_cda));

  // 初始化环境
  int oci_ret = oci_init(&m_env);

  if ( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO )
  {
    oci_close(&m_env); m_cda.rc=-1; strncpy(m_cda.message,"initialize oracle call interface failed.\n",128); return -1;
  }

  // 创建句柄,登录数据库
  oci_ret = oci_context_create(&m_env,&m_cxt);

  if ( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO )
  {
    oci_close(&m_env); m_cda.rc=1017; strncpy(m_cda.message,"ORA-01017: invalid username/password,logon denied.\n",128); return -1;
  }

  m_state = 1;

  m_autocommitopt=autocommitopt;

  return 0;
}

int connection::disconnect()
{
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0) 
  { 
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.",128); return -1;
  }

  rollback();

  oci_context_close(&m_cxt);

  oci_close(&m_env);

  m_state = 0;    

  return 0;
}

int connection::rollback()
{ 
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0) 
  { 
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.",128); return -1;
  }

  int oci_ret = OCITransRollback( m_cxt.svchp, m_cxt.errhp, OCI_DEFAULT ); 

  if ( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO )
  {
    err_report(); return m_cda.rc;
  }

  return 0;    
}

int connection::commit()
{ 
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0) 
  { 
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.",128); return -1;
  }

  int oci_ret = OCITransCommit( m_cxt.svchp, m_cxt.errhp, OCI_DEFAULT );

  if ( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO )
  {
    err_report(); return m_cda.rc;
  }

  return 0;
}

void connection::err_report()
{
  if (m_state == 0) 
  { 
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.",128); return;
  }

  memset(&m_cda,0,sizeof(m_cda));

  m_cda.rc=-1;
  strncpy(m_cda.message,"call err_report failed.",128);

  if (m_cxt.errhp != NULL)
  {
    if (OCIErrorGet(m_cxt.errhp,1,NULL,&m_cda.rc,(OraText*)m_cda.message,sizeof(m_cda.message),OCI_HTYPE_ERROR) == OCI_NO_DATA)
    {
      // 如果获取不到错误信息,就返回正确的
      memset(&m_cda,0,sizeof(m_cda)); return;
    }
  }
}

sqlstatement::sqlstatement()
{
  m_state=0; 

  memset(&m_handle,0,sizeof(m_handle));

  memset(&m_cda,0,sizeof(m_cda));

  memset(m_sql,0,sizeof(m_sql));

  m_cda.rc=-1;
  strncpy(m_cda.message,"sqlstatement not connect to connection.\n",128);
}

sqlstatement::sqlstatement(connection *conn)
{
  sqlstatement();

  connect(conn);
}

sqlstatement::~sqlstatement()
{
  disconnect();
}

int sqlstatement::connect(connection *conn)
{
  // 注意,一个sqlstatement在程序中只能连一个connection,不允许连多个connection
  // 所以,只要这个光标已打开,就不允许再次打开,直接返回成功
  if ( m_state == 1 ) return 0;

  memset(&m_cda,0,sizeof(m_cda));

  m_conn=conn;

  // 如果数据库连接类的指针为空,直接返回失败
  if (m_conn == 0) 
  {
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.\n",128); return -1;
  }

  // 如果数据库没有连接好,直接返回失败
  if (m_conn->m_state == 0) 
  {
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.\n",128); return -1;
  }
    
  m_cda.rc = oci_stmt_create(&m_conn->m_cxt,&m_handle);

  if ( m_cda.rc != OCI_SUCCESS && m_cda.rc != OCI_SUCCESS_WITH_INFO )
  {
    err_report(); return m_cda.rc;
  }

  m_state = 1;  // 光标成功打开

  m_autocommitopt=m_conn->m_autocommitopt;

  m_cda.rc = OCI_SUCCESS; 

  alloclob();

  return 0;
}

int sqlstatement::disconnect()
{
  if (m_state == 0) return 0;

  memset(&m_cda,0,sizeof(m_cda));

  freelob();

  m_cda.rc = oci_stmt_close(&m_handle);

  m_state=0;

  memset(&m_handle,0,sizeof(m_handle));

  memset(&m_cda,0,sizeof(m_cda));

  memset(m_sql,0,sizeof(m_sql));

  m_cda.rc=-1;
  strncpy(m_cda.message,"cursor not open.",128);

  return 0;
}

// 在新的OCI方法中,当SQL语句有错误时,OCIStmtPrepare返回的是0,不是失败
// 所以,程序员在程序中一般不必处理prepare的结果
int sqlstatement::prepare(const char *fmt,...)
{ 
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0) 
  {
    m_cda.rc=-1; strncpy(m_cda.message,"cursor not open.\n",128); return -1;
  }

  memset(m_sql,0,sizeof(m_sql));

  va_list ap;
  va_start(ap,fmt);
  vsnprintf(m_sql,10000,fmt,ap);

  int oci_ret = OCIStmtPrepare(m_handle.smthp,m_handle.errhp,(OraText*)m_sql,strlen(m_sql),OCI_NTV_SYNTAX,OCI_DEFAULT);

  if ( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO )
  {
    err_report(); return m_cda.rc;
  }

  // 判断是否是查询语句,如果是,把m_sqltype设为0,其它语句设为1。
  m_sqltype=1;

  // 从待执行的SQL语句中截取15个字符,如果这15个字符中包括了“select”,就认为是查询语句
  char strtemp[16]; memset(strtemp,0,sizeof(strtemp)); strncpy(strtemp,m_sql,15);

  if ( (strstr(strtemp,"select") > 0) || (strstr(strtemp,"Select") > 0) || (strstr(strtemp,"SELECT") > 0) ) m_sqltype=0; 

  m_cda.rc = OCI_SUCCESS; 

  return 0;
}

int sqlstatement::bindin(unsigned int position,int *value)
{
  return OCIBindByPos(m_handle.smthp, &m_handle.bindhp, m_handle.errhp, (ub4)position, value, sizeof(int),
                        SQLT_INT, NULL, NULL,NULL,0, NULL, OCI_DEFAULT);  
}

int sqlstatement::bindin(unsigned int position,long *value)
{
  return OCIBindByPos(m_handle.smthp, &m_handle.bindhp, m_handle.errhp, (ub4)position, value, sizeof(long),
                        SQLT_INT, NULL, NULL,NULL,0, NULL, OCI_DEFAULT);  
}

int sqlstatement::bindin(unsigned int position,unsigned int *value)
{
  return OCIBindByPos(m_handle.smthp, &m_handle.bindhp,m_handle.errhp,(ub4)position,value,sizeof(unsigned int),
                        SQLT_INT, NULL, NULL,NULL,0, NULL, OCI_DEFAULT);  
}

int sqlstatement::bindin(unsigned int position,unsigned long *value)
{
  return OCIBindByPos(m_handle.smthp,&m_handle.bindhp,m_handle.errhp,(ub4)position,value,sizeof(unsigned long),
                        SQLT_INT, NULL, NULL,NULL,0, NULL, OCI_DEFAULT);  
}

int sqlstatement::bindin(unsigned int position,char *value,unsigned int len)
{
  return OCIBindByPos(m_handle.smthp, &m_handle.bindhp, m_handle.errhp, (ub4)position, value, len+1,
                        SQLT_STR, NULL, NULL,NULL,0, NULL, OCI_DEFAULT);  
}

int sqlstatement::bindin(unsigned int position,float *value)
{
  return OCIBindByPos(m_handle.smthp, &m_handle.bindhp, m_handle.errhp, (ub4)position, value, sizeof(float),
                        SQLT_FLT, NULL, NULL,NULL,0, NULL, OCI_DEFAULT);
}

int sqlstatement::bindin(unsigned int position,double *value)
{
  return OCIBindByPos(m_handle.smthp, &m_handle.bindhp, m_handle.errhp, (ub4)position, value, sizeof(double),
                        SQLT_FLT, NULL, NULL,NULL,0, NULL, OCI_DEFAULT);
}

int sqlstatement::bindout(unsigned int position,int *value)
{
  return OCIDefineByPos(m_handle.smthp, &m_handle.defhp, m_handle.errhp, position, value, sizeof(int), 
                          SQLT_INT, NULL, NULL, NULL, OCI_DEFAULT );
}

int sqlstatement::bindout(unsigned int position,long *value)
{
  return OCIDefineByPos(m_handle.smthp, &m_handle.defhp, m_handle.errhp, position, value, sizeof(long), 
                          SQLT_INT, NULL, NULL, NULL, OCI_DEFAULT );
}

int sqlstatement::bindout(unsigned int position,unsigned int *value)
{
  return OCIDefineByPos(m_handle.smthp, &m_handle.defhp, m_handle.errhp, position, value, sizeof(unsigned int), 
                          SQLT_INT, NULL, NULL, NULL, OCI_DEFAULT );
}
int sqlstatement::bindout(unsigned int position,unsigned long *value)
{
  return OCIDefineByPos(m_handle.smthp, &m_handle.defhp, m_handle.errhp, position, value, sizeof(unsigned long), 
                          SQLT_INT, NULL, NULL, NULL, OCI_DEFAULT );
}

int sqlstatement::bindout(unsigned int position,float *value)
{
  return OCIDefineByPos(m_handle.smthp, &m_handle.defhp, m_handle.errhp, position, value, sizeof(float), 
                          SQLT_FLT, NULL, NULL, NULL, OCI_DEFAULT );
}

int sqlstatement::bindout(unsigned int position,double *value)
{
  return OCIDefineByPos(m_handle.smthp, &m_handle.defhp, m_handle.errhp, position, value, sizeof(double), 
                          SQLT_FLT, NULL, NULL, NULL, OCI_DEFAULT );
}

int sqlstatement::bindout(unsigned int position,char *value,unsigned int len)
{
  return OCIDefineByPos(m_handle.smthp, &m_handle.defhp, m_handle.errhp, position, value, len+1, 
                          SQLT_STR, NULL, NULL, NULL, OCI_DEFAULT );
}

int sqlstatement::bindblob()
{
  return OCIDefineByPos(m_handle.smthp, &m_handle.defhp, m_handle.errhp, 1,(dvoid *) &m_lob,-1, 
                          SQLT_BLOB, NULL, NULL, NULL, OCI_DEFAULT );
}

int sqlstatement::bindclob()
{
  return OCIDefineByPos(m_handle.smthp, &m_handle.defhp, m_handle.errhp, 1,(dvoid *) &m_lob,-1, 
                          SQLT_CLOB, NULL, NULL, NULL, OCI_DEFAULT );
}

int sqlstatement::execute() 
{
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0) 
  {
    m_cda.rc=-1; strncpy(m_cda.message,"cursor not open.\n",128); return -1;
  }

  ub4 mode=OCI_DEFAULT;

  if (m_sqltype==1 && m_autocommitopt==1) mode=OCI_COMMIT_ON_SUCCESS;

  int oci_ret = OCIStmtExecute(m_handle.svchp,m_handle.smthp,m_handle.errhp,m_sqltype,0,NULL,NULL,mode);

  if ( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO )
  {
    // 发生了错误或查询没有结果
    err_report(); return m_cda.rc;
  }

  // 如果不是查询语句,就获取影响记录的行数
  if (m_sqltype == 1)
  {
    OCIAttrGet((CONST dvoid *)m_handle.smthp,OCI_HTYPE_STMT,(dvoid *)&m_cda.rpc, (ub4 *)0,
                OCI_ATTR_ROW_COUNT, m_handle.errhp);
  }

  return 0;
}

int sqlstatement::execute(const char *fmt,...) 
{
  char strtmpsql[10240];
  memset(strtmpsql,0,sizeof(strtmpsql));

  va_list ap;
  va_start(ap,fmt);
  vsnprintf(strtmpsql,10000,fmt,ap);

  if (prepare(strtmpsql) != 0) return m_cda.rc;

  return execute();
}

int sqlstatement::next() 
{ 
  // 注意,在该函数中,不可随意用memset(&m_cda,0,sizeof(m_cda)),否则会清空m_cda.rpc的内容
  if (m_state == 0) 
  {
    m_cda.rc=-1; strncpy(m_cda.message,"cursor not open.\n",128); return -1;
  }

  // 如果语句未执行成功,直接返回失败。
  if (m_cda.rc != 0) return m_cda.rc;

  // 判断是否是查询语句,如果不是,直接返回错误
  if (m_sqltype != 0)
  {
    m_cda.rc=-1; strncpy(m_cda.message,"no recordset found.\n",128); return -1;
  }

  int oci_ret = OCIStmtFetch(m_handle.smthp,m_handle.errhp,1,OCI_FETCH_NEXT,OCI_DEFAULT);

  if ( oci_ret != OCI_SUCCESS && oci_ret != OCI_SUCCESS_WITH_INFO )
  {
    err_report(); 

    // 只有当m_cda.rc不是1405和1406的时候,才返回错误,1405和1406不算错
    // 并且,返回错误的时候,不要清空了m_cda.rpc
    if (m_cda.rc != 1405 && m_cda.rc != 1406) 
    {
      // 如果返回代码不是0,1403,1405,1406,就表是next出现了其它异常
      // 必须关闭数据库连接,让程序错误退出。
      if ( (m_cda.rc!=0) && (m_cda.rc!=1403) && (m_cda.rc!=1405) && (m_cda.rc!=1406) ) m_conn->disconnect();

      return m_cda.rc;
    }
  }

  // 获取结果集成功

  // 如果返回的是1405或1406,就把它强置为0
  if (m_cda.rc == 1405 || m_cda.rc == 1406) m_cda.rc=0;

  // 获取影响记录的行数据
  OCIAttrGet((CONST dvoid *)m_handle.smthp,OCI_HTYPE_STMT,(dvoid *)&m_cda.rpc, (ub4 *)0,
              OCI_ATTR_ROW_COUNT, m_handle.errhp);

  return 0;
}

void sqlstatement::err_report()
{
  // 注意,在该函数中,不可随意用memset(&m_cda,0,sizeof(m_cda)),否则会清空m_cda.rpc的内容
  if (m_state == 0) 
  {
    m_cda.rc=-1; strncpy(m_cda.message,"cursor not open.\n",128); return;
  }

  m_cda.rc=-1;
  strncpy(m_cda.message,"call sqlstatement::err_report() failed.\n",128);

  if (m_handle.errhp != NULL)
  {
    if (OCIErrorGet(m_handle.errhp,1,NULL,&m_cda.rc,(OraText*)m_cda.message,sizeof(m_cda.message),OCI_HTYPE_ERROR) == OCI_NO_DATA)
    {
      // 如果没有获取到任何错误信息,就返回正确的
      // 这里可以用memset清空m_cda,因为如果没有任何错误m_cda.rpc在next中会重新赋值
      m_cda.rc=0; memset(m_cda.message,0,sizeof(m_cda.message)); return;
    }
  }

  m_conn->err_report();
}

int sqlstatement::alloclob()
{
  return OCIDescriptorAlloc((dvoid *)m_handle.envhp,(dvoid **)&m_lob,(ub4)OCI_DTYPE_LOB,(size_t)0,(dvoid **)0);
}

void sqlstatement::freelob()
{
  OCIDescriptorFree((dvoid *)m_lob, (ub4)OCI_DTYPE_LOB);
}


ub4 file_length(FILE *fp)
{
  fseek(fp, 0, SEEK_END);
  return (ub4) (ftell(fp));
}

int  sqlstatement::filetolob(char *filename)
{
  FILE *fp=0;

  if ( (fp = fopen(filename,"rb")) == 0) 
  {
    m_cda.rc=-1; strncpy(m_cda.message,"fopen failed",128); return -1;
  }
  
  int iret = filetolob(fp);

  fclose(fp);

  return iret;
}

/* 操作CLOB和BLOB内容时,缓冲区的大小,一般不需要修改。 */
#define LOBMAXBUFLEN  10240

int sqlstatement::filetolob(FILE *fp)
{
  ub4   offset = 1;
  ub4   loblen = 0;
  ub1   bufp[LOBMAXBUFLEN+1];
  ub4   amtp;
  ub1   piece;
  sword retval;
  ub4   nbytes;
  ub4   remainder;

  ub4  filelen = file_length(fp);

  if (filelen == 0) return 0;

  amtp = filelen;

  remainder = filelen;

  (void) OCILobGetLength(m_handle.svchp, m_handle.errhp, m_lob, &loblen);

  (void) fseek(fp, 0, 0);

  if (filelen > LOBMAXBUFLEN)
  {
    nbytes = LOBMAXBUFLEN;
  }
  else
  {
    nbytes = filelen;
  }

  memset(bufp,0,sizeof(bufp));

  if (fread((void *)bufp, (size_t)nbytes, 1, fp) != 1)
  {
    m_cda.rc=-1; strncpy(m_cda.message,"fread failed",128); return -1;
  }

  remainder -= nbytes;

  if (remainder == 0)       
  {
    // exactly one piece in the file
    // Only one piece, no need for stream write
    if ( (retval = OCILobWrite(m_handle.svchp, m_handle.errhp, m_lob, &amtp, offset, (dvoid *) bufp,
                            (ub4) nbytes, OCI_ONE_PIECE, (dvoid *)0,
                            (sb4 (*)(dvoid *, dvoid *, ub4 *, ub1 *)) 0,
                            (ub2) 0, (ub1) SQLCS_IMPLICIT)) != OCI_SUCCESS)
    {
      err_report(); return m_cda.rc;
    }
  }
  else
  {
    // more than one piece
    if (OCILobWrite(m_handle.svchp, m_handle.errhp, m_lob, &amtp, offset, (dvoid *) bufp,
                    (ub4) LOBMAXBUFLEN, OCI_FIRST_PIECE, (dvoid *)0,
                    (sb4 (*)(dvoid *, dvoid *, ub4 *, ub1 *)) 0,
                    (ub2) 0, (ub1) SQLCS_IMPLICIT) != OCI_NEED_DATA)
    {
      err_report(); return m_cda.rc;
    }

    piece = OCI_NEXT_PIECE;

    do
    {
      if (remainder > LOBMAXBUFLEN)
      {
        nbytes = LOBMAXBUFLEN;
      }
      else
      {
        nbytes = remainder; piece = OCI_LAST_PIECE;
      }

       memset(bufp,0,sizeof(bufp));

      if (fread((void *)bufp, (size_t)nbytes, 1, fp) != 1)
      {
        m_cda.rc=-1; strncpy(m_cda.message,"fread failed",128); return -1;
      }

      retval = OCILobWrite(m_handle.svchp, m_handle.errhp, m_lob, &amtp, offset, (dvoid *) bufp,
                          (ub4) nbytes, piece, (dvoid *)0,
                          (sb4 (*)(dvoid *, dvoid *, ub4 *, ub1 *)) 0,
                          (ub2) 0, (ub1) SQLCS_IMPLICIT);
      remainder -= nbytes;

    } while (retval == OCI_NEED_DATA && !feof(fp));
  }

  if (retval != OCI_SUCCESS)
  {
    err_report(); return m_cda.rc;
  }

  (void) OCILobGetLength(m_handle.svchp, m_handle.errhp, m_lob, &loblen);

  return 0;
}

// 把LOB字段中的内容写入文件
int  sqlstatement::lobtofile(char *filename)
{
  FILE *fp=0;

  if ( (fp = fopen(filename,"wb")) == 0)
  {
    if ( (fp = fopen(filename,"wb")) == 0)
    {
      m_cda.rc=-1; strncpy(m_cda.message,"fopen failed",128); return -1;
    }
  }

  fseek(fp, 0, 0);

  int iret = lobtofile(fp);

  fclose(fp);

  // 如果文件在生成的过程中发生了错误,就删除该文件,因为它是一个不完整的文件
  if (iret != 0) remove(filename); 

  return iret;
}

int sqlstatement::lobtofile(FILE *fp)
{
  ub4   offset = 1;
  ub4   loblen = 0;
  ub1   bufp[LOBMAXBUFLEN+1];
  ub4   amtp = 0;
  sword retval;

  OCILobGetLength(m_handle.svchp, m_handle.errhp, m_lob, &loblen);

  if (loblen == 0) return 0;

  amtp = loblen;

  memset(bufp,0,sizeof(bufp));

  retval = OCILobRead(m_handle.svchp, m_handle.errhp, m_lob, &amtp, offset, (dvoid *) bufp,
                     (loblen < LOBMAXBUFLEN ? loblen : LOBMAXBUFLEN), (dvoid *)0,
                     (sb4 (*)(dvoid *, const dvoid *, ub4, ub1)) 0,
                     (ub2) 0, (ub1) SQLCS_IMPLICIT);

  switch (retval)
  {
    case OCI_SUCCESS:             /* only one piece */
      fwrite((void *)bufp, (size_t)amtp, 1, fp);
      break;

    case OCI_NEED_DATA:           /* there are 2 or more pieces */
      fwrite((void *)bufp, amtp, 1, fp); 

      while (1)
      {
        amtp = 0;
        memset(bufp,0,sizeof(bufp));

        retval = OCILobRead(m_handle.svchp, m_handle.errhp, m_lob, &amtp, offset, (dvoid *) bufp,
                           (ub4) LOBMAXBUFLEN, (dvoid *)0,
                           (sb4 (*)(dvoid *, const dvoid *, ub4, ub1)) 0,
                           (ub2) 0, (ub1) SQLCS_IMPLICIT);

        fwrite((void *)bufp, (size_t)amtp, 1, fp);

        if (retval != OCI_NEED_DATA) break;
      } 

      break;

    case OCI_ERROR:
      err_report(); 

      return m_cda.rc;
  }

  return 0;
}

6._mysql.h

#ifndef __MYSQL_H
#define __MYSQL_H

// C/C++库常用头文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

/* mysql头文件 */
#include <mysql.h>

// mysql登录环境
struct LOGINENV
{
  char ip[32];
  char user[32];     // 数据库的用户名
  char pass[32];     // 数据库的密码
  char dbname[51];  
  int  port;
};

// mysql执行的结果
struct CDA_DEF
{
  int      rc;             // 执行结果
  unsigned long rpc;       // 执行SQL语句后,影响记录的行数
  char     message[2048];  // 执行SQL语句如果失败,存放错误信息
};

/* 数据库连接池类 */
class connection
{
public:
  MYSQL     *m_conn;

  // 连接状态,0-未连接,1-已连接
  int m_state;

  // 服务器环境句柄
  LOGINENV m_env;

  // 自动提交标志,0-关闭自动提交;1-开启自动提交
  int m_autocommitopt; 

  // 数据库种类,固定取值为mysql
  char m_dbtype[21];

  connection();

 ~connection();

  // 连接数据库,
  // connstr的格式为:ip,username,password,dbname,port
  // autocommitopt:0-关闭自动提交,1-启用自动提交
  int connecttodb(char *connstr,char *charset,unsigned int autocommitopt=0);

  // 从connstr中解析ip,username,password,dbname,port
  void setdbopt(char *connstr);

  // 断开与数据库的连接
  int  disconnect();

  // 设置字符集,要与数据库的一致,否则中文会出现乱码
  void character(char *charset);

  // 提交事务
  int  commit(); 

  // 回滚事务
  int  rollback();

  // 获取错误信息
  void err_report();

  // 用于存放connection操作数据库的错误或最后一次执行SQL语句的结果
  CDA_DEF m_cda;
};

// 定义SQL语句中,输入和输出字段个数的最大值,256是很大的了,可以根据实际情况调整
#define MAXPARAMS  256

/* SQL语言数据操作类 */
class sqlstatement
{
public:
  // 与数据库连接池的状态,0-未绑定,1-已绑定
  int m_state;

  // 语句句柄
  MYSQL_STMT *m_handle;
  
  // 输入参数
  MYSQL_BIND params_in[MAXPARAMS];
  // 输出参数
  MYSQL_BIND params_out[MAXPARAMS];

  connection *m_conn;

  // SQL语句
  char m_sql[10240];

  // 执行结果
  CDA_DEF m_cda;

  int m_sqltype;  // 待执行的SQL语句的类型,0-查询语句;1-非查询语句

  // 自动提交标志,0-关闭自动提交;1-开启自动提交
  int m_autocommitopt; 

  sqlstatement();
  sqlstatement(connection *conn);

  void initial();

 ~sqlstatement();

  // 设定数据库连接池
  int  connect(connection *conn); 

  // 断开与数据库连接池的连接
  int  disconnect();

  // 分析SQL语句,支持存储过程,采用立刻分析的方式,即时返回分析结果
  int  prepare(const char *fmt,...);

  // 绑定输入变量的地址
  int  bindin(unsigned int position,int    *value);
  int  bindin(unsigned int position,long   *value);
  int  bindin(unsigned int position,unsigned int  *value);
  int  bindin(unsigned int position,unsigned long *value);
  int  bindin(unsigned int position,float *value);
  int  bindin(unsigned int position,double *value);
  int  bindin(unsigned int position,char   *value,unsigned int len);

  // 绑定输出变量的地址
  int  bindout(unsigned int position,int    *value);
  int  bindout(unsigned int position,long   *value);
  int  bindout(unsigned int position,unsigned int  *value);
  int  bindout(unsigned int position,unsigned long *value);
  int  bindout(unsigned int position,float *value);
  int  bindout(unsigned int position,double *value);
  int  bindout(unsigned int position,char   *value,unsigned int len);

  // 执行SQL语句
  int  execute();

  // 如果SQL语句不需要输入和输出变量,可以直接执行。
  int  execute(const char *fmt,...);

  // 取下一条记录,只有当SQL语句是查询语句时才有意义 
  int  next();

  // 错误报告
  void err_report();
};
#endif

7._mysql.cpp

#include "_mysql.h"
connection::connection()
{ 
  m_conn = NULL;

  m_state = 0; 

  memset(&m_env,0,sizeof(LOGINENV));

  memset(&m_cda,0,sizeof(m_cda));

  m_cda.rc=-1;
  strncpy(m_cda.message,"database not open.",128);

  // 数据库种类
  memset(m_dbtype,0,sizeof(m_dbtype));
  strcpy(m_dbtype,"mysql");
}

connection::~connection()
{
  disconnect();
}

// 从connstr中解析username,password,tnsname
// "120.77.115.3","szidc","SZmb1601","lxqx",3306
void connection::setdbopt(char *connstr)
{
  memset(&m_env,0,sizeof(LOGINENV));

  char *bpos,*epos;

  bpos=epos=0;

  // ip
  bpos=connstr;
  epos=strstr(bpos,",");
  if (epos > 0) 
  {
    strncpy(m_env.ip,bpos,epos-bpos); 
  }else return;

  // user
  bpos=epos+1;
  epos=0;
  epos=strstr(bpos,",");
  if (epos > 0) 
  {
    strncpy(m_env.user,bpos,epos-bpos); 
  }else return;

  // pass
  bpos=epos+1;
  epos=0;
  epos=strstr(bpos,",");
  if (epos > 0) 
  {
    strncpy(m_env.pass,bpos,epos-bpos); 
  }else return;

  // dbname
  bpos=epos+1;
  epos=0;
  epos=strstr(bpos,",");
  if (epos > 0) 
  {
    strncpy(m_env.dbname,bpos,epos-bpos); 
  }else return;

  // port
  m_env.port=atoi(epos+1);
}

int connection::connecttodb(char *connstr,char *charset,unsigned int autocommitopt)
{
  // 如果已连接上数据库,就不再连接
  // 所以,如果想重连数据库,必须显示的调用disconnect()方法后才能重连
  if (m_state == 1) return 0;

  // 从connstr中解析username,password,tnsname
  setdbopt(connstr);

  memset(&m_cda,0,sizeof(m_cda));

  if ( (m_conn = mysql_init(NULL)) == NULL )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"initialize mysql failed.\n",128); return -1;
  }

  if ( mysql_real_connect(m_conn,m_env.ip,m_env.user,m_env.pass,m_env.dbname,m_env.port, NULL, 0 ) == NULL )
  {
    m_cda.rc=mysql_errno(m_conn); strncpy(m_cda.message,mysql_error(m_conn),2000); mysql_close(m_conn); m_conn=NULL;  return -1;
  }

  // 设置事务模式,0-关闭自动提交,1-开启自动提交
  m_autocommitopt=autocommitopt;

  if ( mysql_autocommit(m_conn, m_autocommitopt ) != 0 )
  {
    m_cda.rc=mysql_errno(m_conn); strncpy(m_cda.message,mysql_error(m_conn),2000); mysql_close(m_conn); m_conn=NULL;  return -1;
  }

  // 设置字符集
  character(charset);

  m_state = 1;

  return 0;
}

// 设置字符集,要与数据库的一致,否则中文会出现乱码
void connection::character(char *charset)
{
  mysql_set_character_set(m_conn,charset);

  return;
}

int connection::disconnect()
{
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0) 
  { 
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.",128); return -1;
  }

  rollback();

  mysql_close(m_conn); 

  m_conn=NULL;

  m_state = 0;    

  return 0;
}

int connection::rollback()
{ 
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0) 
  { 
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.",128); return -1;
  }

  if ( mysql_rollback(m_conn ) != 0 )
  {
    m_cda.rc=mysql_errno(m_conn); strncpy(m_cda.message,mysql_error(m_conn),2000); mysql_close(m_conn); m_conn=NULL;  return -1;
  }

  return 0;    
}

int connection::commit()
{ 
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0) 
  { 
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.",128); return -1;
  }

  if ( mysql_commit(m_conn ) != 0 )
  {
    m_cda.rc=mysql_errno(m_conn); strncpy(m_cda.message,mysql_error(m_conn),2000); mysql_close(m_conn); m_conn=NULL;  return -1;
  }

  return 0;
}

void connection::err_report()
{
  if (m_state == 0) 
  { 
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.",128); return;
  }

  memset(&m_cda,0,sizeof(m_cda));

  m_cda.rc=-1;
  strncpy(m_cda.message,"call err_report failed.",128);

  m_cda.rc=mysql_errno(m_conn);

  strncpy(m_cda.message,mysql_error(m_conn),1024);

  return;
}

sqlstatement::sqlstatement()
{
  initial();
}

void sqlstatement::initial()
{
  m_state=0;

  m_handle=NULL;

  memset(&m_cda,0,sizeof(m_cda));

  memset(m_sql,0,sizeof(m_sql));

  m_cda.rc=-1;
  strncpy(m_cda.message,"sqlstatement not connect to connection.\n",128);
}

sqlstatement::sqlstatement(connection *conn)
{
  initial();

  connect(conn);
}

sqlstatement::~sqlstatement()
{
  disconnect();
}

int sqlstatement::connect(connection *conn)
{
  // 注意,一个sqlstatement在程序中只能连一个connection,不允许连多个connection
  // 所以,只要这个光标已打开,就不允许再次打开,直接返回成功
  if ( m_state == 1 ) return 0;
  
  memset(&m_cda,0,sizeof(m_cda));

  m_conn=conn;

  // 如果数据库连接类的指针为空,直接返回失败
  if (m_conn == 0)
  {
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.\n",128); return -1;
  }
  
  // 如果数据库没有连接好,直接返回失败
  if (m_conn->m_state == 0)
  {
    m_cda.rc=-1; strncpy(m_cda.message,"database not open.\n",128); return -1;
  }

  if ( (m_handle=mysql_stmt_init(m_conn->m_conn)) == NULL)
  {
    err_report(); return m_cda.rc;
  }

  m_state = 1;  // 光标成功打开

  m_autocommitopt=m_conn->m_autocommitopt;

  return 0;
}

int sqlstatement::disconnect()
{
  if (m_state == 0) return 0;

  memset(&m_cda,0,sizeof(m_cda));

  mysql_stmt_close(m_handle);

  m_state=0;

  m_handle=NULL;

  memset(&m_cda,0,sizeof(m_cda));

  memset(m_sql,0,sizeof(m_sql));

  m_cda.rc=-1;
  strncpy(m_cda.message,"cursor not open.",128);

  return 0;
}

void sqlstatement::err_report()
{
  // 注意,在该函数中,不可随意用memset(&m_cda,0,sizeof(m_cda)),否则会清空m_cda.rpc的内容
  if (m_state == 0)
  {
    m_cda.rc=-1; strncpy(m_cda.message,"cursor not open.\n",128); return;
  }
  
  memset(&m_conn->m_cda,0,sizeof(m_conn->m_cda));

  m_cda.rc=-1;
  strncpy(m_cda.message,"call err_report() failed.\n",128);

  m_cda.rc=mysql_stmt_errno(m_handle);

  snprintf(m_cda.message,2000,"%d,%s",m_cda.rc,mysql_stmt_error(m_handle));

  m_conn->err_report();

  return;
}
  
int sqlstatement::prepare(const char *fmt,...)
{
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0)
  {
    m_cda.rc=-1; strncpy(m_cda.message,"cursor not open.\n",128); return -1;
  }

  memset(m_sql,0,sizeof(m_sql));

  va_list ap;
  va_start(ap,fmt);
  vsnprintf(m_sql,10000,fmt,ap);
  va_end(ap);

  int ilen=strlen(m_sql);

  // 为了和freeoci兼容,把:1,:2,:3...等替换成?
  for (int ii=0;ii<ilen;ii++)
  {
    if ( (m_sql[ii]==':') && (isdigit(m_sql[ii+1])!=0) )
    {
      m_sql[ii]='?';
      m_sql[ii+1]=' ';
      if (isdigit(m_sql[ii+2])!=0) m_sql[ii+2]=' ';
      if (isdigit(m_sql[ii+3])!=0) m_sql[ii+3]=' ';
    }
  }

  if (mysql_stmt_prepare(m_handle,m_sql,strlen(m_sql)) != 0)
  {
    err_report(); return m_cda.rc;
  }

  // 判断是否是查询语句,如果是,把m_sqltype设为0,其它语句设为1。
  m_sqltype=1;
  
  // 从待执行的SQL语句中截取15个字符,如果这15个字符中包括了“select”,就认为是查询语句
  char strtemp[16]; memset(strtemp,0,sizeof(strtemp)); strncpy(strtemp,m_sql,15);

  if ( (strstr(strtemp,"select") > 0) || (strstr(strtemp,"Select") > 0) || (strstr(strtemp,"SELECT") > 0) ) m_sqltype=0;

  memset(params_in,0,sizeof(params_in));

  memset(params_out,0,sizeof(params_out));

  return 0;
}
  
int sqlstatement::bindin(unsigned int position,int *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->param_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_in[position-1].buffer_type = MYSQL_TYPE_LONG;
  params_in[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindin(unsigned int position,long *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->param_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_in[position-1].buffer_type = MYSQL_TYPE_LONGLONG;
  params_in[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindin(unsigned int position,unsigned int *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->param_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_in[position-1].buffer_type = MYSQL_TYPE_LONG;
  params_in[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindin(unsigned int position,unsigned long *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->param_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_in[position-1].buffer_type = MYSQL_TYPE_LONGLONG;
  params_in[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindin(unsigned int position,char *value,unsigned int len)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->param_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_in[position-1].buffer_type = MYSQL_TYPE_VAR_STRING;
  params_in[position-1].buffer = value;
  params_in[position-1].buffer_length = len;

  return 0;
}

int sqlstatement::bindin(unsigned int position,float *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->param_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_in[position-1].buffer_type = MYSQL_TYPE_FLOAT;
  params_in[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindin(unsigned int position,double *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->param_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_in[position-1].buffer_type = MYSQL_TYPE_DOUBLE;
  params_in[position-1].buffer = value;

  return 0;
}

///
int sqlstatement::bindout(unsigned int position,int *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->field_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_out[position-1].buffer_type = MYSQL_TYPE_LONG;
  params_out[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindout(unsigned int position,long *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->field_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_out[position-1].buffer_type = MYSQL_TYPE_LONGLONG;
  params_out[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindout(unsigned int position,unsigned int *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->field_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_out[position-1].buffer_type = MYSQL_TYPE_LONG;
  params_out[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindout(unsigned int position,unsigned long *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->field_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_out[position-1].buffer_type = MYSQL_TYPE_LONGLONG;
  params_out[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindout(unsigned int position,char *value,unsigned int len)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->field_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_out[position-1].buffer_type = MYSQL_TYPE_VAR_STRING;
  params_out[position-1].buffer = value;
  params_out[position-1].buffer_length = len;

  return 0;
}

int sqlstatement::bindout(unsigned int position,float *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->field_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_out[position-1].buffer_type = MYSQL_TYPE_FLOAT;
  params_out[position-1].buffer = value;

  return 0;
}

int sqlstatement::bindout(unsigned int position,double *value)
{
  if ( (position<1) || (position>=MAXPARAMS) || (position>m_handle->field_count) )
  {
    m_cda.rc=-1; strncpy(m_cda.message,"array bound.",128);
  }

  params_out[position-1].buffer_type = MYSQL_TYPE_DOUBLE;
  params_out[position-1].buffer = value;

  return 0;
}

int sqlstatement::execute()
{
  memset(&m_cda,0,sizeof(m_cda));

  if (m_state == 0)
  {
    m_cda.rc=-1; strncpy(m_cda.message,"cursor not open.\n",128); return -1;
  }

  if ( (m_handle->param_count>0) && (m_handle->bind_param_done == 0))
  {
    if (mysql_stmt_bind_param(m_handle,params_in) != 0)
    {
      err_report(); return m_cda.rc;
    }
  }


  if ( (m_handle->field_count>0) && (m_handle->bind_result_done == 0) )
  {
    if (mysql_stmt_bind_result(m_handle,params_out) != 0)
    {
      err_report(); return m_cda.rc;
    }
  }

  if (mysql_stmt_execute(m_handle) != 0)
  {
    err_report(); return m_cda.rc;
  }
  
  // 如果不是查询语句,就获取影响记录的行数
  if (m_sqltype == 1) m_cda.rpc=m_handle->affected_rows;
    
  return 0;
}

int sqlstatement::execute(const char *fmt,...)
{
  char strtmpsql[10240];
  memset(strtmpsql,0,sizeof(strtmpsql));

  va_list ap;
  va_start(ap,fmt);
  vsnprintf(strtmpsql,10000,fmt,ap);
  va_end(ap);

  if (prepare(strtmpsql) != 0) return m_cda.rc;

  return execute();
}

int sqlstatement::next()
{
  // 注意,在该函数中,不可随意用memset(&m_cda,0,sizeof(m_cda)),否则会清空m_cda.rpc的内容
  if (m_state == 0)
  {
    m_cda.rc=-1; strncpy(m_cda.message,"cursor not open.\n",128); return -1;
  }
  
  // 如果语句未执行成功,直接返回失败。
  if (m_cda.rc != 0) return m_cda.rc;
  
  // 判断是否是查询语句,如果不是,直接返回错误
  if (m_sqltype != 0)
  {
    m_cda.rc=-1; strncpy(m_cda.message,"no recordset found.\n",128); return -1;
  }
  
  int ret=mysql_stmt_fetch(m_handle);

  if (ret==0) 
  { 
    m_cda.rpc++; return 0; 
  }
 
  if (ret==1) 
  {
    err_report(); return m_cda.rc;
  }

  if (ret==MYSQL_NO_DATA) return MYSQL_NO_DATA;

  if (ret==MYSQL_DATA_TRUNCATED) 
  {
    m_cda.rpc++; return 0;
  }
  
  return 0;
}
  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
#0 Homer::RtpSessionState::deprovisionAtDestruction (this=0x7f1fe00e7650) at ../components/mos/state/session_state/src/rtp_session_state.cpp:886 886 ../components/mos/state/session_state/src/rtp_session_state.cpp: No such file or directory. [Current thread is 1 (Thread 0x7f1ffffff700 (LWP 372))] (gdb) bt #0 Homer::RtpSessionState::deprovisionAtDestruction (this=0x7f1fe00e7650) at ../components/mos/state/session_state/src/rtp_session_state.cpp:886 #1 0x00005653759a8e33 in Homer::DeviceState::~DeviceState (this=0x7f1fe00ecf50) at ../components/mos/state/device_state/src/device_state.cpp:87 #2 0x0000565375c4229e in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x7f1fe00ecf40) at /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/shared_ptr_base.h:155 #3 std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count (this=0x7f1fe00bbb08) at /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/shared_ptr_base.h:730 #4 std::__shared_ptr<Homer::DeviceStateBase, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr (this=0x7f1fe00bbb00) at /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/shared_ptr_base.h:1169 #5 Homer::Device::~Device (this=0x7f1fe00bb070) at ../components/mos/device/src/device.cpp:94 #6 0x0000565375c3c08a in Homer::WebsocketDevice::~WebsocketDevice (this=0x7f1fe00bb070) at ../components/mos/device/src/websocket_device.h:31 #7 Homer::WebsocketClientDevice::~WebsocketClientDevice (this=0x7f1fe00bb070) at ../components/mos/device/src/websocket_client_device.cpp:20
06-13

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值