【Linux、C】生成测试数据json、xml、csv文件

CLogFile类:  日志类
CFile类:        文件类
CCmdStr类: 字符串分割类

/*
 *  程序名:crtsurfdata5.cpp  本程序用于生成全国气象站点观测的分钟数据。
 *  作者:陈镖任。
 */
#include "_public.h"
CLogFile logfile;

// 全国气象站点参数结构体。
struct st_stcode
{
    char provname[31]; // 省
    char obtid[11];    // 站号
    char obtname[31];  // 站名
    double lat;        // 纬度
    double lon;        // 经度
    double height;     // 海拔高度
};

// 全国气象站点分钟观测数据结构
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米。
};
// 获取当前时间,当作观测时间。
char strddatetime[21];

// 存放全国气象站点参数的容器。
vector<struct st_stcode> vstcode;

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

vector<struct st_surfdata> vsurfdata; // 存放全国气象站点分钟观测数据的容器

// 模拟生成全国气象站点分钟观测数据,存放在vsurfdata容器中。
void CrtSurfData();

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

int main(int argc, char *argv[])
{
    // initfile outpath logfile
    if (argc != 5)
    {
        printf("Using:./crtsurfdata5 inifile outpath logfile datafmt\n");
        printf("Example:~/project/idc2/c/crtsurfdata5 ~/project/idc2/init/stcode.ini ~/tmp/surfdata ~/log/idc/crtsurfdata5.log xml,json,csv\n\n");

        printf("inifile 全国气象站点参数文件名。\n");
        printf("outpath 全国气象站点数据文件存放的目录。\n");
        printf("logfile 本程序运行的日志文件名。\n\n");
        printf("datafmt 生成数据文件的格式,支持xml、json和csv三种格式,中间用逗号分隔。\n\n");

        return -1;
    }

    // 打开程序的日志文件。
    if (logfile.Open(argv[3], "a+", false) == false)
    {
        printf("logfile.Open(%s) failed.\n", argv[3]);
        return -1;
    }

    logfile.Write("crtsurfdata5 开始运行。\n");

    // 把站点参数文件中加载到vstcode容器中。
    if (LoadSTCode(argv[1]) == false)
        return -1;

    // 模拟生成全国气象站点分钟观测数据,存放在vsurfdata容器中。
    CrtSurfData();

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

    logfile.Write("crtsurfdata5 运行结束。\n");

    return 0;
}

bool LoadSTCode(const char *inifile)
{
    CFile File;

    // 打开站点参数文件。
    if (File.Open(inifile, "r") == false)
    {
        logfile.Write("File.Open(%s) failed.\n", inifile);
        return false;
    }

    char strBuffer[301];

    CCmdStr CmdStr;

    struct st_stcode stcode;

    while (true)
    {
        // 从站点参数文件中读取一行,如果已读取完,跳出循环。
        if (File.Fgets(strBuffer, 300, true) == false)
            break;

        // 把读取到的一行拆分。
        CmdStr.SplitToCmd(strBuffer, ",", true);

        if (CmdStr.CmdCount() != 6)
            continue; // 扔掉无效的行。

        // 把站点参数的每个数据项保存到站点参数结构体中。
        memset(&stcode, 0, sizeof(struct st_stcode));
        CmdStr.GetValue(0, stcode.provname, 30); // 省
        CmdStr.GetValue(1, stcode.obtid, 10);    // 站号
        CmdStr.GetValue(2, stcode.obtname, 30);  // 站名
        CmdStr.GetValue(3, &stcode.lat);         // 纬度
        CmdStr.GetValue(4, &stcode.lon);         // 经度
        CmdStr.GetValue(5, &stcode.height);      // 海拔高度

        // 把站点参数结构体放入站点参数容器。
        vstcode.push_back(stcode);
    }

    /*
    for (auto x : vstcode)
        {
            logfile.Write("provname=%s,obtid=%s,obtname=%s,lat=%.2f,lon=%.2f,height=%.2f\n",
                          x.provname, x.obtid, x.obtname, x.lat,
                          x.lon, x.height);
        }
    */
    return true;
}

// 模拟生成全国气象站点分钟观测数据,存放在vsurfdata容器中。
void CrtSurfData()
{
    // 播随机数种子。
    srand(time(0));

    memset(strddatetime, 0, sizeof(strddatetime));
    LocalTime(strddatetime, "yyyymmddhh24miss");

    struct st_surfdata stsurfdata;

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

        // 用随机数填充分钟观测数据的结构体。
        strncpy(stsurfdata.obtid, vstcode[i].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);
    }
    /*
    cout << vsurfdata.size() << endl;
    for (auto x : vsurfdata)
    {
        cout << x.ddatetime << " " << x.obtid << " " << x.p << " " << x.r << " " << x.t << " " << x.u << " " << x.vis << " " << x.wd << " " << x.wf << endl;
    }
    */
}

// 把容器vsurfdata中的全国气象站点分钟观测数据写入文件。
bool CrtSurfFile(const char *outpath, const char *datafmt)
{
    // 正确文件写入方法:
    // 创建临时文件
    // 往临时文件中写入数据
    // 关闭临时文件
    // 把临时文件改名为正式的文件


    CFile File;

    // 拼接生成数据的文件名,例如:/tmp/idc/surfdata/SURF_ZH_20240117092200_2254.csv
    char strFileName[301];
    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");

    // 遍历存放观测数据的vsurfdata容器。
    for (int i = 0; i < vsurfdata.size(); i++)
    {
        // 写入一条记录。
        if (strcmp(datafmt, "csv") == 0)
            File.Fprintf("%s,%s,%.1f,%.1f,%d,%d,%.1f,%.1f,%.1f\n",
                         vsurfdata[i].obtid, vsurfdata[i].ddatetime, vsurfdata[i].t / 10.0, vsurfdata[i].p / 10.0,
                         vsurfdata[i].u, vsurfdata[i].wd, vsurfdata[i].wf / 10.0, vsurfdata[i].r / 10.0, vsurfdata[i].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[i].obtid, vsurfdata[i].ddatetime, vsurfdata[i].t / 10.0, vsurfdata[i].p / 10.0,
                         vsurfdata[i].u, vsurfdata[i].wd, vsurfdata[i].wf / 10.0, vsurfdata[i].r / 10.0, vsurfdata[i].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[i].obtid, vsurfdata[i].ddatetime, vsurfdata[i].t / 10.0, vsurfdata[i].p / 10.0,
                         vsurfdata[i].u, vsurfdata[i].wd, vsurfdata[i].wf / 10.0, vsurfdata[i].r / 10.0, vsurfdata[i].vis / 10.0);
            if (i < vsurfdata.size() - 1)
                File.Fprintf(",\n");
            else
                File.Fprintf("\n");
        }
    }

    // 关闭文件。
    File.CloseAndRename();

    logfile.Write("生成数据文件%s成功,数据时间%s,记录数%d。\n", strFileName, strddatetime, vsurfdata.size());

    return true;
}

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值