气象项目数据中心开发-服务器-2

3)生成测试数据,模拟观测数据

  • 建立结构体存放全国气象站点分钟观测数据
// 存放全国气象站点参数的容器。
vector<struct st_stcode> vstcode;

// 把站点参数文件中加载到vstcode容器中。
bool LoadSTCode(const char *inifile);

// 全国气象站点分钟观测数据结构
struct st_surfdata
{
  char obtid[11];      // 站点代码。
  char ddatetime[21];  // 数据时间:格式yyyymmddhh24miss
  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米。
};
  • CrtsurfData()函数用于模拟生成全国气象站点分钟观测数据,存放在vsurfdata容器中
// 模拟生成全国气象站点分钟观测数据,存放在vsurfdata容器中。
void CrtSurfData()
{
  // 播随机数种子。
  srand(time(0));

  // 获取当前时间,当作观测时间。
  char strddatetime[21];
  memset(strddatetime,0,sizeof(strddatetime));
  LocalTime(strddatetime,"yyyymmddhh24miss");

  struct st_surfdata stsurfdata;

  // 遍历气象站点参数的vstcode容器。
  for (int ii=0;ii<vstcode.size();ii++)
  {
    memset(&stsurfdata,0,sizeof(struct st_surfdata));

    // 用随机数填充分钟观测数据的结构体。
    strncpy(stsurfdata.obtid,vstcode[ii].obtid,10); // 站点代码。
    strncpy(stsurfdata.ddatetime,strddatetime,14);  // 数据时间:格式yyyymmddhh24miss
    stsurfdata.t=rand()%351;       // 气温:单位,0.1摄氏度
    stsurfdata.p=rand()%265+10000; // 气压:0.1百帕
    stsurfdata.u=rand()%100+1;     // 相对湿度,0-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容器。
    vsurfdata.push_back(stsurfdata);
  }
}
  • gdb调试新增功能
    在这里插入图片描述

在末尾设置断点在这里插入图片描述

查看vsurfdata容器内容
在这里插入图片描述

4)生成.csv/.xml/.json文件

在这里插入图片描述
在这里插入图片描述

添加CrtSurfFile函数用于把容器vsurfdata中的全国气象站点分钟观测数据写入文件。

bool CrtSurfFile(const char *outpath,const char *datafmt)// 把容器vsurfdata中的全国气象站点分钟观测数据写入文件。
{
  CFile File;


  char strFileName[301];// 拼接生成数据的文件名,例如:/tmp/idc/surfdata/SURF_ZH_20210629092200_2254.csv
  sprintf(strFileName,"%s/SURF_ZH_%s_%d.%s",outpath,strddatetime,getpid(),datafmt);


  if (File.OpenForRename(strFileName,"w")==false)// 打开文件。
  {
    logfile.Write("File.OpenForRename(%s) failed.\n",strFileName); return false;
  }


  if (strcmp(datafmt,"csv")==0) File.Fprintf("站点代码,数据时间,气温,气压,相对湿度,风向,风速,降雨量,能见度\n");// 写入第一行标题。


  for (int ii=0;ii<vsurfdata.size();ii++)// 遍历存放观测数据的vsurfdata容器。
  {

    if (strcmp(datafmt,"csv")==0)// 写入一条记录。
      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",strFileName,strddatetime,vsurfdata.size());

  return true;
}

在main函数中加入

if (strstr(argv[4],"xml")!=0) CrtSurfFile(argv[2],"xml"); // 把容器vsurfdata中的全国气象站点分钟观测数据写入文件。
if (strstr(argv[4],"json")!=0) CrtSurfFile(argv[2],"json");
if (strstr(argv[4],"csv")!=0) CrtSurfFile(argv[2],"csv");

在/tmp/idc/surfdata中查看导出文件

在这里插入图片描述

查看csv文件

在这里插入图片描述

json和xml文件格式举例

在这里插入图片描述
在这里插入图片描述

main中添加输入xml和json格式的代码

  if (strcmp(datafmt,"xml")==0) File.Fprintf("<data>\n");
  if (strcmp(datafmt,"json")==0) File.Fprintf("{\"data\":[\n");


  for (int ii=0;ii<vsurfdata.size();ii++)// 遍历存放观测数据的vsurfdata容器。
  {

     if (strcmp(datafmt,"csv")==0)// 写入一条记录。
      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);

     if (strcmp(datafmt,"xml")==0)
      File.Fprintf("<obtid>%s</obtid><ddatetime>%s</ddatetime><t>%.1f</t><p>%.1f</p>"\
                   "<u>%d</u><wd>%d</wd><wf>%.1f</wf><r>%.1f</r><vis>%.1f</vis><endl/>\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);

      if (strcmp(datafmt,"json")==0)
      {
          File.Fprintf("{\"obtid\":\"%s\",\"ddatetime\":\"%s\",\"t\":\"%.1f\",\"p\":\"%.1f\","\
                   "\"u\":\"%d\",\"wd\":\"%d\",\"wf\":\"%.1f\",\"r\":\"%.1f\",\"vis\":\"%.1f\"}",\
         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);
          if (ii<vsurfdata.size()-1) File.Fprintf(",\n");
          else   File.Fprintf("\n");
      }

查看xml和json文件

在这里插入图片描述
在这里插入图片描述

使用服务调度程序procct1自动生成测试数据

  • 服务程序由调度程序周期性启动

  • 想要使crtsurfdata脚本自动化运行【输出三种格式的气象数据文件】,这里利用了Linux的多进程和信号调度的策略,给出源码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc,char *argv[])
{
	if(argc < 3)
	{

	printf("Using:./procct1 timev1 program argv ...\n");
	printf("Example:/project/tools1/bin/procct1 5 /usr/bin/tar zcvf /tmp/program/tmp.tgz /usr/include\n\n");

	printf("本程序是服务程序的调度程序,周期性启动服务程序或shell脚本. \n");
	printf("timetvl 运行周期,单位:秒。 被调度的程序运行结束后,在timetv1秒后会被procct1重新启动\n");

	printf("program 被调度的程序名称,必须使用全路径\n");
	printf("argvs 被调度的程序参数\n");
	printf("注意,本程序不会被kill杀死,但可以用kill -9强行杀死 \n\n\n");
	return -1;
	}
	
	//先执行fork函数,创建一个子进程,让子进程调用execl执行新的程序,
	//新程序将替换子进程,不会影响父进程,
	//在父进程中,可以调用wait函数等待新程序运行的结果,这样就可以实现调度的功能
	
	//程序实现功能 ./procct1 5 /usr/bin/ls -lt /tmp/bak.zip
	for(int ii=0 ;ii<64 ;ii++)
	{//程序员会先屏蔽掉全部的信号
	  signal(ii,SIG_IGN);
	  close(ii);

	}
	if(fork()!=0) exit(0);//生成子进程,父进程退出,让程序运行在后台,由系统1号进程托管.
	
	signal(SIGCHLD,SIG_DFL);//启用SIGCHLD信号,让父进程可以wait子进程退出的状态


	char *pargv[argc];
	for(int ii=2 ;ii<argc;ii++)
	  pargv[ii-2]=argv[ii];
	pargv[argc-2]=NULL;
	

	while(true)
	{
	  if(fork() == 0) //子进程
	  {
		
		execv(argv[2],pargv);
		//execl("/usr/bin/ls","/usr/bin/ls","-lt","/tmp/bak.zip",(char*)0);
		//execl:把当前进程影像替换为新的进程影像(正文段,数据段,堆栈)
		exit(0);

	  }
	  else //父进程
	  {

		int status;
		wait(&status);
		sleep(atoi(argv[1]));
	   }
	}
	
	execl("/usr/bin/ls","/usr/bin/ls","-lt","/tmp/bak.zip",(char*)0);
	//execl:把当前进程影像替换为新的进程影像(正文段,数据段,堆栈) 
	
	return 0;

}

设置时间参数是60s,每60s跑一编crtsurfdata

在这里插入图片描述

查看日志

在这里插入图片描述

可见,生成周期是60s,每1min生成一批测试数据文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值