Linux开发_摄像头编程

举报
DS小龙哥 发表于 2022/05/25 23:10:16 2022/05/25
【摘要】 介绍摄像头编程、完成摄像头拍照保存为BMP图像到本地,贴出解析天气预报、北京时间的例子代码(上篇文章遗留的题目)。

任务1:摄像头操作方式

Linux、windows这些系统下很多摄像头都是免驱(UVC)

v4l2 :免驱摄像头框架----一堆结构体。

Linux下开发摄像头的不同角度问题:(嵌入式开发)

1.​ 上层软件系统开发(系统编程),控制驱动提供的接口使用摄像头。

2.​ 底层硬件系统开发(驱动编程),直接控制摄像头采集数据。

摄像头功能:将采集到的图像数据转为二进制数据返回。

驱动的代码集成在操作系统里。

在操作系统里使用摄像头步骤:学习接口函数的调用。

fread(); read();

Linux下是一切设备皆文件: 摄像头、网卡、声卡、鼠标、键盘………………….

Linux下设备文件存放的位置: /dev目录下。


在虚拟机跑Linux,使用外设设备都需要单独挂载才可以使用。

​ 挂载摄像头:

​ 查看摄像头的设备节点:

[root@wbyq /]# ls /dev/video*

/dev/video0 /dev/video1

​ 远程网页视频监控示例

libjpeg-turbo-1.2.1.tar.gz : 将图片数据可以压缩成jpeg数据流。Jpg图片。

mjpg-streamer-r63.tar.gz : 采集摄像头的数据,进行处理。

一张240*320的24位色bmp图片大小: 240*320*3

第一步:编译libjpeg-turbo

1. 解压:libjpeg-turbo-1.2.1.tar.gz

2. 生成Makefile(如果报错,就安装报错提示安装包):./configure

3. 编译安装:make && make install

4. 将生成lib和include目录下的文件拷贝到/usr目录下的对应文件夹


第二步:编译mjpg-streamer-r63

1.直接make进行编译

2.运行程序:./mjpg_streamer -i "/work/mjpeg/mjpg-streamer-r63/input_uvc.so -f 10 -r 800*480 -y" -o "/work/mjpeg/mjpg-streamer-r63/output_http.so -w www"

注意: 可以使用电脑自带的摄像头。在虚拟机的右下角进行将windows系统的摄像头挂载到Linux系统

3. 在浏览器里输入地址进行查看摄像头:

例如:192.168.11.123:8080

作业:

1.​ 将远程摄像头监控的代码编译运行实现效果。

(1)​ 修改端口号,8080不能作为公网的端口访问。

(2)​ 修改线程数量。

(3)​ 分析下线程的函数实现原理。

(4)​ 使用花生壳软件实现公网监控。

花生壳: 将本地IP地址映射为一个域名。

外网想要访问本地电脑IP就直接访问域名。

2.​ 学习摄像头的使用

1.​ 摄像头实现拍照源程序流程:(50%程序学过的)

2.​ 打开摄像头的设备文件 open(“/dev/xxx”);

3.​ 获取摄像头参数。判断摄像头是否支持一些特有的操作。read

4.​ 配置摄像头的参数。(1) 输出的源数据格式RGB888 (2) 输出的图像尺寸

RGB888:数字数据格式

其他格式: YUV 模拟数据格式

5.​ 判断摄像头的参数是否设置成功。

6.​ 读取摄像头的数据。 队列的形式。

7.​ 将读取的YUV格式数据转为RGB格式

8.​ 将RGB格式数据编码为BMP格式的图片存放到电脑上

​ 安装rpm软件包:rpm -ivh xxxxx.rpm

​ Linux下安装软件有两种方式:

1.​ rpm软件安装包(已经编译好的二进制文件的集合),使用rpm -ivh xxx.rpm

2.​ 直接下载源码包自己编译安装。libjpeg-turbo-1.2.1.tar.gz

(1)​ 没有makefile文件,就有: configure文件,用来生成makefile文件

示例: ./configure

(2)​ make 编译源码

(3)​ make install 安装源码。(会将编译好的文件拷贝到指定的目录下)


void *memset(void *s, int c, size_t count) //给指定地址的空间填入指定大小的数据

参数:

*s :起始地址

c :填入的数据

count :填入的数量


RGB888 : 000 FFF


(0)摄像头拍照

#include "camera_bmp.h"

T_PixelDatas Pixedata; //存放实际的图像数据

/*
		USB摄像头相关参数定义
*/
struct v4l2_buffer tV4l2Buf;
int iFd;
int ListNum;
unsigned char* pucVideBuf[4];  // 视频BUFF空间地址

int main(int argc ,char *argv[])
{
	if(argc!=2)
	{
		  printf("./app /dev/videoX\n");
		  return -1;
	}
	
	camera_init(argv[1]);  //摄像头设备初始化

	//开始采集摄像头数据,并编码保存为BMP图片
	camera_pthread();
	return 0;
}


//YUV转RGB实现
unsigned int Pyuv422torgb32(unsigned char * ptr,unsigned int width, unsigned int height)
{
	unsigned int i, size;
	unsigned char Y, Y1, U, V;
	unsigned char *buff = ptr;         //源数据
	unsigned char *output_pt=Pixedata.VideoBuf; //存放转换之后的数据
 	unsigned char r, g, b;
	size = width * height /2;
	for (i = size; i > 0; i--) 
	{
		Y = buff[0];
		U = buff[1];
		Y1= buff[2];
		V = buff[3];
		buff += 4;
		r = R_FROMYV(Y,V);
		g = G_FROMYUV(Y,U,V); //b
		b = B_FROMYU(Y,U); //v
		*output_pt++ = b;
		*output_pt++ = g;
		*output_pt++ = r;
		r = R_FROMYV(Y1,V);
		g = G_FROMYUV(Y1,U,V); //b
		b = B_FROMYU(Y1,U); //v
		*output_pt++ = b;
		*output_pt++ = g;
		*output_pt++ = r;
	}
	return 0;
} 

//摄像头设备的初始化
int camera_init(char *video)
{
	int i=0;
	int cnt=0;
	//定义摄像头驱动的BUF的功能捕获视频
	int iType = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	
	/* 1、打开视频设备 */
	iFd = open(video,O_RDWR);
	if(iFd < 0)
	{
		printf("摄像头设备打开失败!\n");
		return 0;
	}
	
	struct v4l2_format  tV4l2Fmt;
	
	/* 2、 VIDIOC_S_FMT 设置摄像头使用哪种格式 */
	memset(&tV4l2Fmt, 0, sizeof(struct v4l2_format));
	tV4l2Fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //视频捕获

	//设置摄像头输出的图像格式
    tV4l2Fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;

	/*设置输出的尺寸*/
	tV4l2Fmt.fmt.pix.width       = 640;
	tV4l2Fmt.fmt.pix.height      = 480;
	tV4l2Fmt.fmt.pix.field       = V4L2_FIELD_ANY;
	
    //VIDIOC_S_FMT 设置摄像头的输出参数
    ioctl(iFd, VIDIOC_S_FMT, &tV4l2Fmt); 

	//打印摄像头实际的输出参数
	printf("Support Format:%d\n",tV4l2Fmt.fmt.pix.pixelformat);
	printf("Support width:%d\n",tV4l2Fmt.fmt.pix.width);
	printf("Support height:%d\n",tV4l2Fmt.fmt.pix.height);

	/* 初始化Pixedata结构体,为转化做准备 */
	Pixedata.iBpp =24;								
	//高度 和宽度的赋值
	Pixedata.iHeight = tV4l2Fmt.fmt.pix.height;
	Pixedata.iWidth = tV4l2Fmt.fmt.pix.width;

	//一行所需要的字节数
	Pixedata.iLineBytes = Pixedata.iWidth*Pixedata.iBpp/8;
	//一帧图像的字节数
	Pixedata.iTotalBytes = Pixedata.iLineBytes * Pixedata.iHeight;
	Pixedata.VideoBuf=malloc(Pixedata.iTotalBytes); //申请存放图片数据空间

	//v412请求命令
	struct v4l2_requestbuffers tV4l2ReqBuffs;
	
	/* 3、VIDIOC_REQBUFS  申请buffer */
	memset(&tV4l2ReqBuffs, 0, sizeof(struct v4l2_requestbuffers));

	/* 分配4个buffer:实际上由VIDIOC_REQBUFS获取到的信息来决定 */
	tV4l2ReqBuffs.count   = 4;
	
	/*支持视频捕获功能*/
	tV4l2ReqBuffs.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	
	/* 表示申请的缓冲是支持MMAP */
	tV4l2ReqBuffs.memory  = V4L2_MEMORY_MMAP;
	
	/* 为分配buffer做准备 */
	ioctl(iFd, VIDIOC_REQBUFS, &tV4l2ReqBuffs);
	
	for (i = 0; i < tV4l2ReqBuffs.count; i++) 
	{
		memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
		tV4l2Buf.index = i;
		tV4l2Buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		tV4l2Buf.memory = V4L2_MEMORY_MMAP;

		/* 6、VIDIOC_QUERYBUF 确定每一个buffer的信息 并且 mmap */
		ioctl(iFd, VIDIOC_QUERYBUF, &tV4l2Buf);
		//映射空间地址
		pucVideBuf[i] = mmap(0 /* start anywhere */ ,
				  tV4l2Buf.length, PROT_READ, MAP_SHARED, iFd,
				  tV4l2Buf.m.offset);
		printf("mmap %d addr:%p\n",i,pucVideBuf[i]);
	}

	/* 4、VIDIOC_QBUF  放入队列*/
    for (i = 0; i <tV4l2ReqBuffs.count; i++) 
    {
    	memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
    	tV4l2Buf.index = i;
    	tV4l2Buf.type  = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    	tV4l2Buf.memory = V4L2_MEMORY_MMAP;
    	ioctl(iFd, VIDIOC_QBUF, &tV4l2Buf); //放入队列
    }
	
	/*5、启动摄像头开始读数据*/
    ioctl(iFd, VIDIOC_STREAMON, &iType);
	return 0;
}


/*循环采集摄像头数据*/
void camera_pthread()
{
	int error;
	int cnt=0;
	int i=0;
	int ListNum;
	
	/* 8.1、等待是否有数据 */
	fd_set readfds;
	 
	/* YUV格式的数据<------>在LCD上显示:rgb888 */
	initLut();
	printf("开始采集数据.......\n");
	FD_ZERO(&readfds);
	FD_SET(iFd,&readfds);
	select(iFd+1,&readfds,NULL,NULL,NULL);
  
	memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
	tV4l2Buf.type    = V4L2_BUF_TYPE_VIDEO_CAPTURE; //类型
	tV4l2Buf.memory  = V4L2_MEMORY_MMAP; //存储空间类型

	/* 9、VIDIOC_DQBUF    从队列中取出 */
	error = ioctl(iFd, VIDIOC_DQBUF, &tV4l2Buf); //取出一帧数据
	ListNum = tV4l2Buf.index; //索引编号
	
	//将YUV转换为RGB
	Pyuv422torgb32(pucVideBuf[ListNum],Pixedata.iWidth,Pixedata.iHeight);
	
	//保存BMP
	save_bmp(Pixedata.VideoBuf); 
	memset(&tV4l2Buf, 0, sizeof(struct v4l2_buffer));
	tV4l2Buf.index  = ListNum;
	tV4l2Buf.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	tV4l2Buf.memory = V4L2_MEMORY_MMAP;
	error = ioctl(iFd, VIDIOC_QBUF, &tV4l2Buf);
}


/*-----------------保存为BMP格式的图片------------------*/
typedef unsigned char  BYTE;
typedef unsigned short	WORD;
typedef unsigned long  DWORD;

#pragma pack(1)
typedef struct tagBITMAPFILEHEADER{
     WORD	  bfType;                // the flag of bmp, value is "BM"
     DWORD    bfSize;                // size BMP file ,unit is bytes
     DWORD    bfReserved;            // 0
     DWORD    bfOffBits;             // must be 54  RGB数据存放位置
}BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER{
     DWORD    biSize;            // must be 0x28
     DWORD    biWidth;           // 宽度
     DWORD    biHeight;          // 高度
     WORD     biPlanes;          // must be 1
     WORD	  biBitCount;            // 像素位数
     DWORD    biCompression;         //
     DWORD    biSizeImage;       //
     DWORD    biXPelsPerMeter;   //
     DWORD    biYPelsPerMeter;   //
     DWORD    biClrUsed;             //
     DWORD    biClrImportant;        //
}BITMAPINFOHEADER;


//保存为BMP格式的文件
void save_bmp(char *src)
{
	/*-----------------------------------------------------------
					获取时间参数,用来给图片命名
	-------------------------------------------------------------*/
	time_t t;
    struct tm *tmp;
    char buffer[1024] = {0};
    t = time(NULL);
    tmp=localtime(&t);
    if(strftime(buffer, sizeof(buffer), "%Y%m%d%H%M%S_", tmp) == 0) 
    {
    	printf("timer error\n");
    }
	
	static int cnt=0;      //静态变量存放总数量
	cnt++;
	if(cnt>=20)cnt=0;      //清理计数器
	char str[10];
	sprintf(str,"%d",cnt); //整数转为字符串
	
	strcat(buffer,str);
	strcat(buffer,".bmp");
	printf("%s\n",buffer); //打印图片的名称
	
	/*-----------------------------------------------------------
						获取图片数据,用来保存为BMP图片格式
	-------------------------------------------------------------*/
    FILE * fp;
    int i;
    BITMAPFILEHEADER   bf;
    BITMAPINFOHEADER   bi;
   
    memset(&bf ,0 ,sizeof(BITMAPFILEHEADER));
    memset(&bi ,0 ,sizeof(BITMAPINFOHEADER));

    fp = fopen(buffer, "wb");
    if(!fp)
    {
		printf("open %s error\n",buffer);
		return ;
	}

	//Set BITMAPINFOHEADER 设置BMP信息头
	bi.biSize = sizeof(BITMAPINFOHEADER);//40;
	bi.biWidth  = Pixedata.iWidth;//IMAGEWIDTH;
	bi.biHeight = Pixedata.iHeight;//IMAGEHEIGHT;
	bi.biPlanes = 1;
	bi.biBitCount = 24;//8;
	bi.biCompression = 0;
	bi.biSizeImage =Pixedata.iHeight*Pixedata.iWidth*3; //;0
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;// 1<<(bi.biBitCount)
	bi.biClrImportant = 0;

    //Set BITMAPFILEHEADER
    bf.bfType = 0x4d42; //'B''M'
    bf.bfSize = 54 + bi.biSizeImage;// sizeof(BITMAPFILEHEADER);    
    bf.bfReserved = 0;
    bf.bfOffBits = 54;
       
    fwrite(&bf, sizeof(BITMAPFILEHEADER), 1, fp);
    fwrite(&bi, sizeof(BITMAPINFOHEADER), 1, fp);    
    fwrite(src, Pixedata.iWidth*Pixedata.iHeight*3,1,fp);
    fclose(fp);
}

/*----------------------YUV转RGB算法-------------------*/

static int *LutYr = NULL;
static int *LutYg = NULL;;
static int *LutYb = NULL;;
static int *LutVr = NULL;;
static int *LutVrY = NULL;;
static int *LutUb = NULL;;
static int *LutUbY = NULL;;
static int *LutRv = NULL;
static int *LutGu = NULL;
static int *LutGv = NULL;
static int *LutBu = NULL;


unsigned char RGB24_TO_Y(unsigned char r, unsigned char g, unsigned char b)
{
	return (LutYr[(r)] + LutYg[(g)] + LutYb[(b)]);
}

unsigned char YR_TO_V(unsigned char r, unsigned char y)
{
	return (LutVr[(r)] + LutVrY[(y)]);
}

unsigned char YB_TO_U(unsigned char b, unsigned char y)
{
	return (LutUb[(b)] + LutUbY[(y)]);
}

unsigned char R_FROMYV(unsigned char y, unsigned char v)
{
	return CLIP((y) + LutRv[(v)]);
}

unsigned char G_FROMYUV(unsigned char y, unsigned char u, unsigned char v)
{
	return CLIP((y) + LutGu[(u)] + LutGv[(v)]);
}

unsigned char B_FROMYU(unsigned char y, unsigned char u)
{
	return CLIP((y) + LutBu[(u)]);
}

void initLut(void)
{
	int i;
	#define Rcoef 299 
	#define Gcoef 587 
	#define Bcoef 114 
	#define Vrcoef 711 //656 //877 
	#define Ubcoef 560 //500 //493 564
	
	#define CoefRv 1402
	#define CoefGu 714 // 344
	#define CoefGv 344 // 714
	#define CoefBu 1772
	
	LutYr = malloc(256*sizeof(int));
	LutYg = malloc(256*sizeof(int));
	LutYb = malloc(256*sizeof(int));
	LutVr = malloc(256*sizeof(int));
	LutVrY = malloc(256*sizeof(int));
	LutUb = malloc(256*sizeof(int));
	LutUbY = malloc(256*sizeof(int));
	
	LutRv = malloc(256*sizeof(int));
	LutGu = malloc(256*sizeof(int));
	LutGv = malloc(256*sizeof(int));
	LutBu = malloc(256*sizeof(int));
	for (i= 0;i < 256;i++)
	{
	    LutYr[i] = i*Rcoef/1000 ;
	    LutYg[i] = i*Gcoef/1000 ;
	    LutYb[i] = i*Bcoef/1000 ;
	    LutVr[i] = i*Vrcoef/1000;
	    LutUb[i] = i*Ubcoef/1000;
	    LutVrY[i] = 128 -(i*Vrcoef/1000);
	    LutUbY[i] = 128 -(i*Ubcoef/1000);
	    LutRv[i] = (i-128)*CoefRv/1000;
	    LutBu[i] = (i-128)*CoefBu/1000;
	    LutGu[i] = (128-i)*CoefGu/1000;
	    LutGv[i] = (128-i)*CoefGv/1000;
	}	
}


void freeLut(void)
{
	free(LutYr);
	free(LutYg);
	free(LutYb);
	free(LutVr);
	free(LutVrY);
	free(LutUb);
	free(LutUbY);
	
	free(LutRv);
	free(LutGu);
	free(LutGv);
	free(LutBu);
}

(1)解析北京时间

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

/*
标准时间运行格式: ./app
*/
int GetData(char *src);
int main(int argc,char **argv)
{	
	/*1. 拼接访问的链接路径*/
	char src[200];
	char str[]="http://api.k780.com:88/?app=life.time'&'appkey=10003'&'sign=b59bc3ef6191eb9f747dd4e83c99f2a4'&'format=json >data.txt";
	
	strcpy(src,"curl ");
	strcat(src,str);
	system(src);  //执行浏览器数据
	
	/*2. 读取源数据*/
	FILE *file=fopen("data.txt","rb");
	if(file==NULL)
	{
		printf("文件打开失败!\n");
		exit(-1);
	}
	
	struct stat file_stat_buf;
	stat("data.txt",&file_stat_buf); //获取文件的状态
	
	char *src_data=malloc(file_stat_buf.st_size);
	if(src_data==NULL)
	{
		printf("%s文件第%d行,出现错误:空间失败!\n",__FILE__,__LINE__);
		exit(-1);
	}
	
	fread(src_data,1,file_stat_buf.st_size,file); //读取源数据到缓冲区
	
	/*3. 数据解析*/
	GetData(src_data);
	
	/*4. 释放空间*/
	free(src_data);
	return 0;
}

/*
函数功能:获取具体的数据
函数形参:保存json的源数据首地址
*/
int GetData(char *src)
{
	/*1. 载入源数据,获取根对象*/
	cJSON *root=cJSON_Parse(src);
	if(root==NULL)
	{
		printf("%s文件第%d行,出现错误:获取根对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	
	/*2. 获取对象中的值*/
	cJSON *json=cJSON_GetObjectItem(root,"success");
	if(json==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	
	//判断获取的值是否成功
	if(strcmp(json->valuestring,"1")!=0)
	{
		printf("%s文件第%d行,出现错误:时间获取失败!\n",__FILE__,__LINE__);
		return -1;
	}
	
	
	//获取结果
	json=cJSON_GetObjectItem(root,"result");
	if(json==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	
	//获取秒单位时间
	cJSON *data=cJSON_GetObjectItem(json,"timestamp");
	if(data==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	printf("秒单位的时间:%s\n",data->valuestring);
	
	data=cJSON_GetObjectItem(json,"datetime_1");
	if(data==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	printf("datetime_1:%s\n",data->valuestring);
	
	data=cJSON_GetObjectItem(json,"datetime_2");
	if(data==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	printf("datetime_2:%s\n",data->valuestring);
	
	
	data=cJSON_GetObjectItem(json,"week_1");
	if(data==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	printf("week_1:%s\n",data->valuestring);
	
	
	data=cJSON_GetObjectItem(json,"week_2");
	if(data==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	printf("week_2:%s\n",data->valuestring);
	
	data=cJSON_GetObjectItem(json,"week_3");
	if(data==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	printf("week_3:%s\n",data->valuestring);
	
	data=cJSON_GetObjectItem(json,"week_4");
	if(data==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	printf("week_4:%s\n",data->valuestring);
	/* */
	cJSON_Delete(root);
}

(2)解析天气预报

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

/*
标准时间运行格式: ./app
*/
int GetData(char *src);
int main(int argc,char **argv)
{	
	if(argc!=2)
	{
		printf("参数格式: ./app <城市名称>\n");
		return 0;
	}
	/*1. 拼接访问的链接路径*/
	char src[200];
	char str1[]="http://api.k780.com:88/?app=weather.future'&'weaid=";
	char str2[]="'&&'appkey=10003'&'sign=b59bc3ef6191eb9f747dd4e83c99f2a4'&'format=json >data.txt";
	
	strcpy(src,"curl ");
	strcat(src,str1);
	strcat(src,argv[1]);
	strcat(src,str2);
	
	system(src);  //执行浏览器数据
	
	/*2. 读取源数据*/
	FILE *file=fopen("data.txt","rb");
	if(file==NULL)
	{
		printf("文件打开失败!\n");
		exit(-1);
	}
	
	struct stat file_stat_buf;
	stat("data.txt",&file_stat_buf); //获取文件的状态
	
	char *src_data=malloc(file_stat_buf.st_size);
	if(src_data==NULL)
	{
		printf("%s文件第%d行,出现错误:空间失败!\n",__FILE__,__LINE__);
		exit(-1);
	}
	
	fread(src_data,1,file_stat_buf.st_size,file); //读取源数据到缓冲区
	
	/*3. 数据解析*/
	GetData(src_data);
	
	/*4. 释放空间*/
	free(src_data);
	return 0;
}

/*
函数功能:获取具体的数据
函数形参:保存json的源数据首地址
*/
int GetData(char *src)
{
	/*1. 载入源数据,获取根对象*/
	cJSON *root=cJSON_Parse(src);
	if(root==NULL)
	{
		printf("%s文件第%d行,出现错误:获取根对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	
	/*2. 获取对象中的值*/
	cJSON *json=cJSON_GetObjectItem(root,"success");
	if(json==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}
	
	//判断获取的值是否成功
	if(strcmp(json->valuestring,"1")!=0)
	{
		printf("%s文件第%d行,出现错误:时间获取失败!\n",__FILE__,__LINE__);
		return -1;
	}
	
	
	//获取结果
	json=cJSON_GetObjectItem(root,"result");
	if(json==NULL)
	{
		printf("%s文件第%d行,出现错误:获取json对象失败!\n",__FILE__,__LINE__);
		return -1;
	}

	//获取数组大小
	int cnt=cJSON_GetArraySize(json); 
	printf("cnt=%d\n",cnt);
	int i;
	for(i=0;i<cnt;i++)
	{
		cJSON *data=cJSON_GetArrayItem(json,i);
		
		cJSON *p=cJSON_GetObjectItem(data,"weaid");
		printf("weaid=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"days");
		printf("days=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"week");
		printf("week=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"cityno");
		printf("cityno=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"citynm");
		printf("citynm=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"cityid");
		printf("cityid=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"temperature");
		printf("temperature=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"humidity");
		printf("humidity=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"weather");
		printf("weather=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"wind");
		printf("wind=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"winp");
		printf("winp=%s\n",p->valuestring);
		
		p=cJSON_GetObjectItem(data,"winp");
		printf("winp=%s\n",p->valuestring);
		printf("\n\n");
	}
	cJSON_Delete(root);
}


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。