C/C++7天气APP:生成观测数据txt/xml文件(crtsurfdata.cpp),ftp协议及ftp采集模块(_ftp.h,_ftp.cpp,ftpgetfiles.cpp)

Posted 码农编程录

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C/C++7天气APP:生成观测数据txt/xml文件(crtsurfdata.cpp),ftp协议及ftp采集模块(_ftp.h,_ftp.cpp,ftpgetfiles.cpp)相关的知识,希望对你有一定的参考价值。


1.生成数据:段错误,crontab


根据全国839个气象站点参数生成站点的观测数据如下。

气象站点数据参数链接,ini文件夹下vi stcode.ini填入:填不进去说明数据有问题,直接删除或修改
https://pan.baidu.com/s/1QL5TK3mcowVjCIPPCdhstw 提取码:0p53

打开文件一行一行读出来,字符拆分存入结构体再存入容器:mkdir qxidc/,cd qxidc/,mkdir src bin ini data,data/ftp/surfdata/,cd src/,vi makefile如下

// 记住复制时第一行完整CC,一个tab缩进。crtsurfdata:crtsurfdata.cpp _public.h _public.cpp即 _public.h _public.cpp改变也要重新编译。
CC=g++
FLAG=-g
#FLAG=-02

all:crtsurfdata
crtsurfdata:crtsurfdata.cpp _public.h _public.cpp
        $(CC) $(FLAG) -o crtsurfdata crtsurfdata.cpp _public.cpp
        cp crtsurfdata ../bin/.
clean:
        rm -rf crtsurfdata

如下main函数的参数第一行指针的数组,第二行指针的指针,两行都可以。

LocalTime这么写,默认第二和三个参数为0。

如果第二个参数为0,strlen里不允许为空。

下面在int main函数中测试,strlen里为空会出现段错误。

改为如下就不会报段错误。

日志切换怎么做的:先把日志文件关闭,生成日志备份的文件名再rename,重新打开新的日志文件。 在多进程中不能采用日志切换的方法,在某一个进程中关闭指针文件,其他就全部关了不会再打开。

如下logfile.Open时第三个参数是否备份,默认是true备份(多进程中必须设为false)。第四个参数默认false。


如下mkdir logbak,如下将压缩后的文件放入logbak文件中。

如果2秒这样执行很频繁的话,自身调度没问题,但像60s一分钟执行一次(运行一次1秒都不到就过去了),挂着一分钟会常驻内存浪费系统资源。所以用linux中crontab,每个用户都有自己的crontab任务调度。

cron(特定时间点执行shell指令)是unix下自带的工具,伴随着系统的启动,是一个守护进程。如下是cron表达式,后面接空格再加上要执行的shell脚本。

如下每星期每月每日每小时的第20分钟到第40分钟每分钟都会执行一次(1小时执行21次)。[20,40]是对20-40的说明。


crontab -e进入如下,dow表示星期。


* * * * *是每分钟执行一次,如下共60行整个模拟每秒执行一次,如下长方框是shell脚本。

如下每年每月1号和15号的2点20分执行一次【while(true)和sleep删了,执行一次1秒左右只生成一个文件】。

如下是crtsurfdata.cpp生成全国气象站点观测的分钟数据:结构体值,容器值,txt文件。

#include "_public.h" // 安徽,58102,亳州,33.47,115.44,39.1,_public.h同目录
// 全国气象 (站点参数stcode) 数据结构
struct st_stcode

  char provname[31];   // 省名称
  char obtid[11];      // 站点代码 //也可能是字母所以用字符串表达
  char cityname[31];   // 城市名
  double lat;          // 纬度
  double lon;          // 经度
  double height;       // 海拔高度
;
// 全国气象站点分钟 (生成的观测数据surfdata) 数据结构
struct st_surfdata

  char obtid[11];      // 站点代码
  char ddatetime[21];  // 数据时间:格式yyyy-mm-dd hh24: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米
; 
vector<struct st_stcode> vstcode;   // 存放全国站点参数的容器  //将结构体放入容器中,就直接操作容器了
vector<struct st_surfdata> vsurfdata;   // 存放全国气象站点分钟观测数据的容器
// 从站点参数文件中加载到vstcode容器中,在函数里字符串只能传地址
bool LoadSTCode(const char *inifile);
// 创建全国气象站点分钟观测数据,存放在vsurfdata容器中
void CrtSurfData();
// 把容器vsurfdata中的全国气象站点分钟观测数据写入文件
bool CrtSurfFile(const char *outpath);
CLogFile logfile;   
void EXIT(int sig);

int main(int argc,char *argv[],char *envp[])    //*argv[]:指针的数组,也可以**argv指针的指针
  
  if (argc!=4)
    
    printf("\\n本程序用于生成全国气象站点观测的分钟数据。\\n");
    printf("/root/qxidc/bin/crtsurfdata 站点参数 数据文件存放的目录 日志文件名\\n");
    printf("例如:/root/qxidc/bin/crtsurfdata /root/qxidc/ini/stcode.ini /root/qxidc/data/ftp/surfdata /root/qxidc/log/crtsurfdata.log\\n");  //目录自动创建
    return -1;  //程序没有捕获运行结果,所以0,-1无所谓,return -1失败跳出大循环,return 0成功
  
  // 关闭全部输入输出和信号,也可写成void CloseIOAndSignal(); 下面printf失效
  CloseIOAndSignal();
  // 因为程序运行需要退出,所以捕获退出信号(ctrl+c或kill/kill all),signal将这两个信号值作为sig参数传给EXIT函数
  signal(SIGINT,EXIT); signal(SIGTERM,EXIT);  //可以ctrl+c或kill/kill all通知程序退出  
  if (logfile.Open(argv[3],"a+")==false)
  
    printf("打开日志文件失败(%s)。\\n",argv[3]); return -1;
  
  while (true)  //可把while (true)一行和sleep(60)去除,用crontab调度
  
    // 从站点参数文件中加载到vstcode容器中,argv[0]计算机从0开始
    if (LoadSTCode(argv[1])==false)  sleep(60); continue;     
    logfile.Write("加载参数文件(%s)成功!\\n",argv[1]);
    CrtSurfData();  // 生成全国气象站点分钟观测数据,存放在vsurfdata容器中
    // 把容器vsurfdata中的全国气象站点分钟观测数据写入文件
    if (CrtSurfFile(argv[2])==false)  sleep(60); continue; 
    sleep(60);  // 进入死循环60s执行一次,自身调度自己
  
  return 0;
 

//11111111111111111111.从站点参数文件中加载到vstcode容器中
bool LoadSTCode(const char *inifile)

  vstcode.clear();
  CCmdStr CmdStr;  // CmdStr类(_public.h中)切分并暂存字符串
  struct st_stcode stcode;  // st_stcode为数据结构,stcode为结构体变量
  CFile File;
  if (File.Open(inifile,"r") == false)
  
    logfile.Write("File.Open(%s) 失败。\\n",inifile); return false;
  
  char strbuffer[101];  //101个字节可以存放50个汉字  strbuffer就是stcode.ini站点参数内容
  while (true)
  
    memset(&stcode,0,sizeof(struct st_stcode));
    // memset(strbuffer,0,sizeof(strbuffer)); 因为Fgets里有初始化,所以这行省去    
    if (File.Fgets(strbuffer,100)==false) break; // 读取一行,在循环里就多行读取,break不能写成return false
    CmdStr.SplitToCmd(strbuffer,",",true); // true为删除空格,CmdStr里存了一行拆分后的片段,循环里就是多行
    CmdStr.GetValue(0, stcode.provname);  //stcode.provname就存了拆分的值,在循环里
    CmdStr.GetValue(1, stcode.obtid);     //GetValue做了重载,有第三个参数取长度
    CmdStr.GetValue(2, stcode.cityname);
    CmdStr.GetValue(3,&stcode.lat);  //double 传地址&
    CmdStr.GetValue(4,&stcode.lon);     
    CmdStr.GetValue(5,&stcode.height);
    vstcode.push_back(stcode);	
	// printf("strbuffer=%s",strbuffer);   //不需写成strbuffer=%s\\n,因为文件本身有换行符
	// printf("provname=%s,obtid=%s,lat=%.2lf\\n.....",stcode.provname,stcode.obtid,stcode.lat,......);
  
  return true;


//1111111111111111112.创建全国气象站点分钟观测数据,存放在vsurfdata容器中,//Crt是create缩写
void CrtSurfData()  // 返回一定会成功的,所以不需要返回值void

  vsurfdata.clear();  // 清空容器
  srand(time(0));     // 播随机数种子  
  char strLocalTime[21];  
  LocalTime(strLocalTime,"yyyy-mm-dd hh24:mi"); // LocalTime3个参数:一:存放时间的字符串。二:取出当前时间用什么格式。三:时间偏移量秒。将memset(strLocalTime,0,sizeof(strLocalTime));放入LocalTime()中
  strcat(strLocalTime,":00"); //不计秒,里面800多行记录时间和文件名时间一样就把秒变成00
  struct st_surfdata stsurfdata;
  for (int ii=0;ii<vstcode.size();ii++)  //根据站点代码个数
  
    memset(&stsurfdata,0,sizeof(struct st_surfdata)); 
    STRCPY(stsurfdata.obtid,10,vstcode[ii].obtid);  // 站点代码  //STRCPY(目的,长度,源)
    // LocalTime(stsurfdata.ddatetime);
    STRCPY(stsurfdata.ddatetime,20,strLocalTime);   // 数据时间采用当前时间
    stsurfdata.t=rand()%351;       // 气温:单位,0.1摄氏度  // 结构体值 //0-350间整数就行
    stsurfdata.p=rand()%265+10000; // 气压:0.1百帕  //0到264再加10000就是10000到10264
    stsurfdata.u=rand()%100+1;     // 相对湿度,1-100之间的值。
    stsurfdata.wd=rand()%360;      // 风向,0-360之间的值。
    stsurfdata.wf=rand()%150;      // 风速:单位0.1m/s
    stsurfdata.r=rand()%16;        // 降雨量:0.1mm
    stsurfdata.vis=rand()%5001+100000;  // 能见度:0.1米
    vsurfdata.push_back(stsurfdata);
  


//1111111111111111113.把容器vsurfdata中的全国气象站点分钟观测数据写入文件
bool CrtSurfFile(const char *outpath)

  CFile File;
  char strLocalTime[21];
  LocalTime(strLocalTime,"yyyymmddhh24miss");
  char strFileName[301]; //目录名+文件名即下行outpath+/SURF_ZH_%s_%d.txt,初始化也在SNPRINTF中
  SNPRINTF(strFileName,300,"%s/SURF_ZH_%s_%d.txt",outpath,strLocalTime,getpid());  // outpath目录名   
  if (File.OpenForRename(strFileName,"w")==false)
  
    logfile.Write("File.Open(%s) 失败!\\n",strFileName); return false; // 不用printf显示到屏幕了
  
  for (int ii=0;ii<vsurfdata.size();ii++) //装进容器里就是为了这行循环
  
    // 站点代码,数据时间,气温,气压,相对湿度,风向,风速,降雨量,能见度  //存进容器的是整数,除以小数得小数显示到文件中
    File.Fprintf("%s,%s,%.1f,%.1f,%d,%d,%.1f,%.1f,%.1f\\n",\\
         vsurfdata[ii].obtid,vsurfdata[ii].ddatetime,vsurfdata[ii].t/10.0,vsurfdata[ii].p/10.0,\\
         vsurfdata[ii].u,vsurfdata[ii].wd,vsurfdata[ii].wf/10.0,vsurfdata[ii].r/10.0,vsurfdata[ii].vis/10.0);
  
  File.CloseAndRename();   // 关闭文件
  logfile.Write("生成数据文件(%s)成功,数据时间=%s,记录数=%d!\\n\\n",strFileName,vsurfdata[0].ddatetime,vsurfdata.size()); 
  // 数据时间=和文件名时间一样就是最后秒改为00(即文件里839行【vsurfdata.size()行】记录时间)
  vstcode.clear(); vsurfdata.clear(); //这里不清空容器,记录数=839,1678....(除非每次运行都重新make,不然要清空容器)
  return true;

void EXIT(int sig)

  logfile.Write("程序退出,sig=%d\\n\\n",sig);  // killall crtsurfdata ,.log日志文件中记录了:时间..程序退出,sig=15
  exit(0); //exit(0)程序退出自然会调用logfile的析构函数,所以这里不需要调用


一个.ini文件839行记录不同时间可生成多个.txt文件也有839行记录,一个.txt文件站点代码不同但时间一样。下面为改进版可选择生成.xml文件。

//crtsurfdata1.cpp生成的数据文件支持txt和xml两种格式。
#include "_public.h"
#include "_shqx.h" // _shqx.h里包含st_stcode,st_surfdata两个结构体
vector<struct st_stcode> vstcode;   // 存放全国站点参数的容器
vector<struct st_surfdata> vsurfdata;   // 存放全国气象站点分钟观测数据的容器
// 从站点参数文件中加载到vstcode容器中
bool LoadSTCode(const char *inifile);
// 创建全国气象站点分钟观测数据,存放在vsurfdata容器中
void CrtSurfData();
// 把容器vsurfdata中的全国气象站点分钟观测数据写入文件
bool CrtSurfFile(const char *outpath,const char *datafmt);
CLogFile logfile;
void EXIT(int sig);

int main(int argc,char *argv[],char *envp[])

  if (argc!=5)
  
    printf("\\n本程序用于生成全国气象站点观测的分钟数据,与crtsurfdata程序不同,本程序生成的数据文件支持txt和xml两种格式。\\n");
    printf("/htidc/shqx/bin/crtsurfdata1 站点参数 数据文件存放的目录 日志文件名 数据格式[txt|xml]\\n");
    printf("例如:/htidc/shqx/bin/crtsurfdata1 /htidc/shqx/ini/stcode.ini /data/shqx/ftp/surfdata1 /log/shqx/crtsurfdata1.log txt\\n");
    printf("      /htidc/shqx/bin/crtsurfdata1 /htidc/shqx/ini/stcode.ini /data/shqx/ftp/surfdata1 /log/shqx/crtsurfdata1.log xml\\n");
    return -1;
  
  // 关闭全部的信号和输入输出
  CloseIOAndSignal();
  // 处理程序退出的信号
  signal(SIGINT,EXIT); signal(SIGTERM,EXIT);
  if (logfile.Open(argv[3],"a+")==false)
  
    printf("打开日志文件失败(%s)。\\n",argv[3]); return -1;
  
  while (true)
  
    // 从站点参数文件中加载到vstcode容器中
    if (LoadSTCode(argv[1])==false)  sleep(60); continue; 
    logfile.Write("加载参数文件(%s)成功!\\n",argv[1]);
    CrtSurfData();  // 创建全国气象站点分钟观测数据,存放在vsurfdata容器中
    // 把容器vsurfdata中的全国气象站点分钟观测数据写入文件
    if (CrtSurfFile(argv[2],argv[4])==false)  sleep(60); continue; 
    sleep(60);
  
  return 0;


//1111111111111111111.从站点参数文件中加载到vstcode容器中
bool LoadSTCode(const char *inifile)

  vstcode.clear();
  CCmdStr CmdStr;
  struct st_stcode stcode;
  CFile File;
  if (File.Open(inifile,"r") == false)
  
    logfile.Write("File.Open(%s) 失败。\\n",inifile); return false;
  
  char strbuffer[101];
  while (true)
  
    memset(&stcode,0,sizeof(struct st_stcode));
    if (File.Fgets(strbuffer,100)==false) break;
    CmdStr.SplitToCmd(strbuffer,",",true);
    CmdStr.GetValue(0, stcode.provname);  //结构体值
    CmdStr.GetValue(1, stcode.obtid);
    CmdStr.GetValue(2, stcode.cityname);
    CmdStr.GetValue(3,&stcode.lat);
    CmdStr.GetValue(4,&stcode.lon);
    CmdStr.GetValue(5,&stcode.height);
    vstcode.push_back(stcode);
  
  return true;


//1111111111111111112.创建全国气象站点分钟观测数据,存放在vsurfdata容器中
void CrtSurfData()

  vsurfdata.clear();  // 清空容器
  srand(time(0));  // 播随机数种子
  char

以上是关于C/C++7天气APP:生成观测数据txt/xml文件(crtsurfdata.cpp),ftp协议及ftp采集模块(_ftp.h,_ftp.cpp,ftpgetfiles.cpp)的主要内容,如果未能解决你的问题,请参考以下文章

C/C++8天气APP:Oracle数据库安装,表操作,C语言操作Oracle数据库

C/C++12天气APP:不同数据建表入表,数据交换(exptables.cpp,ftpputfiles.cpp)

C/C++9天气APP:Oracle的虚表/日期/序列,索引/视图/链路/同义词,数据库高可用性

C/C++15天气APP:服务端(client.cpp,shtqappserver.cpp)

快讯·11月7日全省首部视频识别天气现象设备落户德令哈...

C/C++13天气APP:数据挖掘/HTTP协议/非结构化数据存储(filetoblob.cpp),数据管理/监控告警(hsmtable.cpp,tbspaceinfo.cpp)