C/C++11天气APP:txt/xml文件处理入库(psurfdata.cpp,_shqx.h),数据结构设计(PowerDesigner)
Posted 码农编程录
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++11天气APP:txt/xml文件处理入库(psurfdata.cpp,_shqx.h),数据结构设计(PowerDesigner)相关的知识,希望对你有一定的参考价值。
文章目录
1.txt/xml文件入表/自身调度:结构体内容
// makefile
#oracle头文件路径
ORAINCL = -I$(ORACLE_HOME)/rdbms/public
# oracle库文件路径
ORALIB = -L$(ORACLE_HOME)/lib -L.
# oracle的oci库
ORALIBS = -lclntsh
CC=g++
CFLAGS = -g -Wno-write-strings -Wno-unused-variable
all:crtsurfdata libftp.a demo18 ftpgetfile psurfdata
libftp.a:ftplib.c
gcc -c -o libftp.a ftplib.c
demo18:demo18.cpp _ftp.h _ftp.cpp libftp.a
g++ $(CFLAGS) -o demo18 demo18.cpp _public.cpp _ftp.cpp libftp.a
ftpgetfile:ftpgetfile.cpp _ftp.h _ftp.cpp libftp.a
$(CC) $(CFLAGS) -o ftpgetfile ftpgetfile.cpp _public.cpp _ftp.cpp libftp.a
cp ftpgetfile ../bin/.
crtsurfdata:crtsurfdata.cpp _public.h _public.cpp
$(CC) $(CFLAGS) -o crtsurfdata crtsurfdata.cpp _public.cpp
cp crtsurfdata ../bin/.
psurfdata:psurfdata.cpp _public.h _public.cpp
g++ $(CFLAGS) -o psurfdata psurfdata.cpp $(ORAINCL) $(ORALIB) $(ORALIBS) _public.cpp _ooci.cpp
cp psurfdata ../bin/.
clean:
rm -rf crtsurfdata demo18 ftpgetfile libftp psurfdata
//psurfdata.cpp未封装成类
//本程序用于处理全国气象站点观测的分钟数据,并保存到数据库的T_SURFDATA表中。txt文件里面内容以逗号分隔
#include "_public.h"
#include "_ooci.h"
struct st_surfdata // 全国气象站点分钟观测数据结构
char obtid[11]; // 站点代码
char ddatetime[21]; // 数据时间:格式yyyy-mm-dd hh:mi:ss。
int t; // 气温:单位,0.1摄氏度
int p; // 气压:0.1百帕
int u; // 相对湿度,0-100之间的值。
int wd; // 风向,0-360之间的值。
int wf; // 风速:单位0.1m/s
int r; // 降雨量:0.1mm
int vis; // 能见度:0.1米
;
CLogFile logfile;
CDir Dir;
bool _psurfdata(); // 处理数据文件
connection conn;
void EXIT(int sig);
int main(int argc,char *argv[])
if (argc!=5)
printf("\\n本程序用于处理全国气象站点观测的分钟数据,并保存到数据库的T_SURFDATA表中。\\n");
printf("/oracle/lian/qxidc/bin/psurfdata 数据文件存放的目录 日志文件名 数据库连接参数 程序运行时间间隔\\n");
printf("例如:/oracle/lian/qxidc/bin/psurfdata /oracle/lian/qxidc/tmp /oracle/lian/qxidc/log/psurfdata.log scott/tiger@snorcl11g_138 10\\n");
return -1; //失败跳出main函数,必须在装有oracle主机中运行,不然_ooci中路径报错
CloseIOAndSignal(); // 关闭全部的信号和输入输出
signal(SIGINT,EXIT); signal(SIGTERM,EXIT); // 处理程序退出的信号
if (logfile.Open(argv[2],"a+")==false)
printf("打开日志文件失败(%s)。\\n",argv[2]); return -1;
logfile.Write("程序启动。\\n");
while (true)
//1111111111111111111111111111111111111111111111111.扫描数据文件存放的目录
//logfile.Write("开始扫描目录。\\n"); //打开目录拿到文件名放入string型容器里,需排序的话就把这容器排序(先生成先处理)
if (Dir.OpenDir(argv[1],"SURF_ZH_*.txt",1000,true,true)==false) //OpenDir第四个参数是否打开子目录,第五个参数是否排序
logfile.Write("Dir.OpenDir(%s) failed.\\n",argv[1]); sleep(atoi(argv[4])); continue;
//11111111111111111111111111111111111111111111111.逐个处理目录中的数据文件
while (true)
if (Dir.ReadDir()==false) break; //false为读完了
//logfile.Write("%s,%s,%s,%d,%s,%s,%s,%s\\n",Dir.m_DirName,Dir.m_FileName,Dir.m_FullFileName,Dir.m_FileSize,Dir.m_ModifyTime,Dir.m_CreateTime,Dir.m_AccessTime);
//111111111111111111111111111111111111111111111111.连接数据库
if (conn.m_state==0) //0未连接
if (conn.connecttodb(argv[3],"Simplified Chinese_China.ZHS16GBK")!=0)
logfile.Write("connect database(%s) failed.\\n%s\\n",argv[3],conn.m_cda.message); break;
// logfile.Write("连接数据库成功。\\n");
//1111111111111111111111111111111111111111111111111.处理入库
logfile.Write("开始处理文件%s...",Dir.m_FileName); //开头有时间
if (_psurfdata()==false)
logfile.WriteEx("失败。\\n"); break;
logfile.WriteEx("成功。\\n"); //不写时间,不换行,显示屏一行放不下
if (conn.m_state==1) conn.disconnect(); //断开与数据库的连接
sleep(atoi(argv[4]));
return 0;
void EXIT(int sig)
logfile.Write("程序退出,sig=%d\\n\\n",sig);
exit(0);
//1111111111111111111111111111111111111111111111.处理入库
bool _psurfdata()
CFile File; //打开文件
if (File.Open(Dir.m_FullFileName,"r")==false) //Dir的成员变量m_FullFileName也叫属性
logfile.Write("(File.Open(%s) failed.\\n",Dir.m_FullFileName); return false;
char strBuffer[301];
CCmdStr CmdStr;
struct st_surfdata stsurfdata;//定义stsurfdata结构体变量
int iccount=0; //int型初始化
sqlstatement stmtsel(&conn);//select * 返回多行多列的结果集,bindin绑定选择行,bindout绑定选择列
stmtsel.prepare("select count(*) from T_SURFDATA where obtid=:1 and ddatetime=to_date(:2,'yyyy-mm-dd hh24:mi:ss')");
stmtsel.bindin( 1, stsurfdata.obtid,5); // 定义的是字符串不用&
stmtsel.bindin( 2, stsurfdata.ddatetime,19);
stmtsel.bindout(1,&iccount); //select count(*)返回行数即一个数字赋给iccount这个变量,这个数字也是1列,所以bindout中1对应这列
sqlstatement stmtins(&conn);
stmtins.prepare("insert into T_SURFDATA(obtid,ddatetime,t,p,u,wd,wf,r,vis) values(:1,to_date(:2,'yyyy-mm-dd hh24:mi:ss'),:3,:4,:5,:6,:7,:8,:9)");
stmtins.bindin( 1, stsurfdata.obtid,5); //1对应:1 //,crttime,keyid //values里可加:,sysdate,SEQ_SURFDATA.nextval
stmtins.bindin( 2, stsurfdata.ddatetime,19);
stmtins.bindin( 3,&stsurfdata.t);
stmtins.bindin( 4,&stsurfdata.p);
stmtins.bindin( 5,&stsurfdata.u);
stmtins.bindin( 6,&stsurfdata.wd);
stmtins.bindin( 7,&stsurfdata.wf);
stmtins.bindin( 8,&stsurfdata.r);
stmtins.bindin( 9,&stsurfdata.vis);
while (true) //读取文件中的每一行记录并写入数据库的表中
memset(strBuffer,0,sizeof(strBuffer));
if (File.Fgets(strBuffer,300,true)==false) break; //Fgets从文件中读取一行放入strBuffer,第三个参数为是否删除最后空格
// logfile.Write("%s\\n",strBuffer); strBuffer内容为58436,2020-02-09 12:11:00,32.4,1006.9,99,249,11.8,0.2,10107.3
CmdStr.SplitToCmd(strBuffer,",",true); //以,号拆分成9个片段存入CmdStr中
if (CmdStr.CmdCount()!=9)
logfile.Write("%s\\n",strBuffer); continue;
memset(&stsurfdata,0,sizeof(struct st_surfdata)); //sizeof里一般用结构体类型,传变量名的话若是指针就不好了
CmdStr.GetValue(0,stsurfdata.obtid,5); // 站点代码 赋值给stsurfdata.obtid
CmdStr.GetValue(1,stsurfdata.ddatetime,19); // 数据时间:格式yyyy-mm-dd hh:mi:ss。
double dtmp=0;
CmdStr.GetValue(2,&dtmp); stsurfdata.t=(int)(dtmp*10); // 气温:单位,0.1摄氏度
CmdStr.GetValue(3,&dtmp); stsurfdata.p=(int)(dtmp*10); // 气压:0.1百帕
CmdStr.GetValue(4,&stsurfdata.u); // 相对湿度,0-100之间的值。
CmdStr.GetValue(5,&stsurfdata.wd); // 风向,0-360之间的值。
CmdStr.GetValue(6,&dtmp); stsurfdata.wf=(int)(dtmp*10); // 风速:单位0.1m/s
CmdStr.GetValue(7,&dtmp); stsurfdata.r=(int)(dtmp*10); // 降雨量:0.1mm
CmdStr.GetValue(8,&dtmp); stsurfdata.vis=(int)(dtmp*10); // 能见度:0.1米
if (stmtsel.execute() != 0)
logfile.Write("stmtsel.execute() failed.\\n%s\\n%s\\n",stmtsel.m_sql,stmtsel.m_cda.message);
if ( (stmtsel.m_cda.rc>=3113) && (stmtsel.m_cda.rc<=3115) ) return false; //3113-3115是数据库连接失败
continue;
iccount=0;
stmtsel.next(); //把"select count(*)....."这个sql查询结果一次一次取结果集赋给绑定输出的变量即iccount
//这里比较特殊刚好一行一列即一个数字
if (iccount>0) continue; //有记录不执行插入
if (stmtins.execute() != 0) // 执行SQL语句,一定要判断返回值,0-成功,其它-失败
//往数据库里插入,如果记录存在不应该退出,应该跳过已存在的记录
if (stmtins.m_cda.rc!=1) //!=1才是真正的失败,=1是主键冲突,若是主键冲突可以跳过不入库不要返回失败
logfile.Write("%s\\n",strBuffer);
logfile.Write("stmtins.execute() failed.\\n%s\\n%s\\n",stmtins.m_sql,stmtins.m_cda.message);
if ( (stmtins.m_cda.rc>=3113) && (stmtins.m_cda.rc<=3115) ) return false;
//处理生成数据就是先扫描目录,读取目录下文件。读到文件名后打开一文件,一行一行解析出数据插入数据库表里,关闭文件,提交事务
conn.commit();
// 关闭文件指针,并删除文件,不删除会重复读取
File.CloseAndRemove();
return true;
vi psurfdata.log,如下子目录下的文件也读取到了。
如下在_psurfdata()里思路是读一行,按,号拆分,将每个内容读出来再*10放入数据库。
vi /htidc/shqx/ini/stcode1.ini 。
在_shqx.cpp中有InsertTable()成员函数,有select,insert,update及各个的execute()。如下如果记录在表里已存在就执行stmtupt.execute()
,不存在就执行stmtins.execute()
,不管是这两个执行,只要出错,无效的记录数invalidcount就+1,成功的话updatacount和insertcount都+1。
如下时间和文件名一样,但站点不一样 ,59287这个站点是存在的即外键存在。
以下是自身的调度:1.
以下将psurfdata.cpp改为程序自身调度,不用crontab调度。每10秒钟扫描一次目录,有文件的话就连接数据库。
如下为什么不在while(true)扫描目录前连上数据库?假设数据一分钟生成一个文件,处理一个文件入库一秒不到,所以一直连着数据库浪费资源,扫描到有文件处理就连数据库。
如下数据库没连上也不用return -1,只要psurfdata.cpp启动后就一直运行,遇到错误也不能退出,所以改为break只跳出这个小循环
,继续往下面执行,日志还是会写“connect database…failed”。
2.
以下crtsurfdata中自身调度。
结构体可存不同数据类型,需解析xml,将值放入结构体再访问。start.sh里面放crt.,ftp.,p…三个启动脚本并最后加&符。
//将psurfdata.cpp,txt文件入库封成类
#include "_public.h"
#include "_ooci.h"
#include "_shqx.h"
CLogFile logfile;
CDir Dir;
bool _psurfdata();
connection conn; //实例化对象,con也叫变量(称呼)
void EXIT(int sig);
int main(int argc,char *argv[])
if (argc!=5)
printf("\\n本程序用于处理全国气象站点观测的分钟数据,并保存到数据库的T_SURFDATA表中。\\n");
printf("这是完善后的程序,未完善的程序在psurfdata_old.cpp中。\\n");
printf("/htidc/shqx/bin/psurfdata 数据文件存放的目录 日志文件名 数据库连接参数 程序运行时间间隔\\n");
printf("例如:/htidc/shqx/bin/psurfdata /data/shqx/sdata/surfdata /log/shqx/psurfdata.log shqx/pwdidc@snorcl11g_198 10\\n");
return -1;
CloseIOAndSignal();
signal(SIGINT,EXIT); signal(SIGTERM,EXIT);
if (logfile.Open(argv[2],"a+")==false)
printf("打开日志文件失败(%s)。\\n",argv[2]); return -1;
logfile.Write("程序启动。\\n");
while (true)
//111111111111111111111111111111111111111111111.扫描数据文件存放的目录,只匹配"SURF_ZH_*.txt"
// logfile.Write("开始扫描目录。\\n");
if (Dir.OpenDir(argv[1],"SURF_ZH_*.txt",1000,true,true)==false)
logfile.Write("Dir.OpenDir(%s) failed.\\n",argv[1]); sleep(atoi(argv[4])); continue;
//11111111111111111111111111111111111111111111111.连接数据库
while (true)
if (Dir.ReadDir()==false) break;
if (conn.m_state==0)
if (conn.connecttodb(argv[3],"Simplified Chinese_China.ZHS16GBK")!=0)
logfile.Write("connect database(%s) failed.\\n%s\\n",argv[3],conn.m_cda.message); break;
// logfile.Write("连接数据库成功。\\n");
logfile.Write("开始处理文件%s...",Dir.m_FileName);
//111111111111111111111111111111111111111111111111.处理入库
if (_psurfdata()==false)
logfile.WriteEx("失败。\\n"); break;
if (conn.m_state==1) conn.disconnect(); // 断开与数据库的连接
sleep(以上是关于C/C++11天气APP:txt/xml文件处理入库(psurfdata.cpp,_shqx.h),数据结构设计(PowerDesigner)的主要内容,如果未能解决你的问题,请参考以下文章
C/C++14天气APP:文件传输系统(tcpput/getfile.cpp客户端,tcpfileserver.cpp)