龙空技术网

C实现拷贝文件的进度编译成库后QT调用函数获取进度后显示进度条

QT教程 182

前言:

目前大家对“c语言文本文件读取数据”大约比较看重,小伙伴们都需要剖析一些“c语言文本文件读取数据”的相关知识。那么小编同时在网摘上搜集了一些对于“c语言文本文件读取数据””的相关知识,希望各位老铁们能喜欢,咱们快快来学习一下吧!

曾经做过一个嵌入式项目,用c编写了一个获取拷贝文件进度的库,这个库要在QT中使用,Qt获取拷贝的进度,然后在界面显示出来:c库实现获取拷贝的进度,留有回调函数的接口,然后再Qt中注册这个回调函数,C库每次获取拷贝进度后会将进度值通过回调返回给Qt

整个代码的核心就是在.h文件中定义回调函数,定义设置回调函数的一个库函数

然后在.c文件中实现设置回调的库函数,以便给QT使用,QT会使用设置回调的库函数将代表自身的this指针传递,这样就可以使用了

c库

在.h文件中定义回调函数

#ifndef __FILE_CTRL_H_#define __FILE_CTRL_H_#include "db_ctrl.h"#ifdef __cplusplusextern "C" {#endif/** 定义回调函数 */typedef void (*progress_callback)(int progress, void *userPtr);/*** @description: 设置回调函数* @param {*} cb 回调函数指针* @return {*}*/int file_setCallback(progress_callback cb, void *userPtr);/*** @description:把文件拷贝到目录* @param {char} *file_name 源文件名* @param {char} *dir_name 目的文件目录* @return {*}*/int file_copyFileToDir(char *file_name, char *dir_name);/*** @description: 删除文件* @param {*}char *file_name 被删除源文件* @return {*}*/int file_deleteFile(char *file_name);/*** @description: 视频文件压缩* @param {*}* @return {*}*/int file_compressVideoFile(ST_VIDEO_DB_DATA stVideoDbData, char *videoFileName);/*** @description: 视频文件解压缩* @param {*}* @return {*}*/int file_UncompressVideoFile(ST_VIDEO_DB_DATA *stVideoDbData, char *videoFileName, char *zipName);/*** @description: 压缩日志文件夹* @param {char} *LogFileName* @return {*}*/int file_compressLogFile(char *LogFileName);/*** @description:获取带后缀文件名的两个函数* @param {char} *filePath* @return {*}*/char *GetFileName1(char *filePath);#ifdef __cplusplus}#endif#endif

在.c文件中实现设置回调函数

#include <stdio.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>#include <stdlib.h>#include <string.h>#include <pthread.h>#include "file_ctrl.h"#include <time.h>#include <sys/stat.h>#include <fcntl.h>#include "string_parse.h"/** 全局回调函数 */static progress_callback g_cb;static void *g_userPtr;void *get_frate_fmc(void *args);typedef struct {char file_name[128];char dir_name[128];progress_callback cb;void *userPtr;int run_flag;}ST_GET_RATE;/** 设置回调函数 */int file_setCallback(progress_callback cb, void *userPtr){g_cb = cb;g_userPtr = userPtr;return 0;}/** 获取速率线程状态 */void *get_frate_fmc(void *args){ST_GET_RATE *pstGetRate = (ST_GET_RATE*)args;int nSrcFileSize = 0;int nDestFileSize = 0, nDestTempSize = 0;int fRate = 0;int test = 0;/** 获得原文件的大小 */nSrcFileSize = getFileSize(pstGetRate->file_name);while(1){sleep(1);/** 如果run_flag为0,退出线程 */if(pstGetRate->run_flag == 0){pstGetRate->cb(100, pstGetRate->userPtr);break;}// 如果dir_name为0,采用定时发送进度信息if(strlen(pstGetRate->dir_name) == 0){fRate++;if(pstGetRate->cb) pstGetRate->cb(fRate, pstGetRate->userPtr); //进度通过回调发送出去continue;}/** 获得目的文件的大小 */nDestTempSize = getFileSize(pstGetRate->dir_name);if(nDestTempSize == 0)nDestFileSize += 6000;elsenDestFileSize = nDestTempSize;/*** 计算复制的进度 */if(nSrcFileSize) {fRate = nDestFileSize * 100 / nSrcFileSize;if(pstGetRate->cb) pstGetRate->cb(fRate, pstGetRate->userPtr); //进度通过回调发送出去}/** 复制完成之后,退出循环 */if (nSrcFileSize == nDestFileSize){if(pstGetRate->cb) pstGetRate->cb(100, pstGetRate->userPtr);break;}}}/** 拷贝一个文件到一个目录 */int file_copyFileToDir(char *file_name,char *dir_name){int ret;pthread_t pth;/** shell执行的命令 ,在创建文件的时候使用*/char szExcueCommand[150] = {0};ST_GET_RATE stGetRate;strcpy(stGetRate.file_name, file_name);strcpy(stGetRate.dir_name, dir_name);stGetRate.cb = g_cb;stGetRate.userPtr = g_userPtr;stGetRate.run_flag = 1;// 创建线程ret = pthread_create(&pth, NULL, get_frate_fmc, (void*)&stGetRate);if(ret < 0){printf("Create pthread for \'\' is Failed - %d!\n", ret);return -1;}// 执行拷贝sprintf(szExcueCommand,"cp %s %s",file_name,dir_name);system(szExcueCommand);// 关闭线程,等待线程结束stGetRate.run_flag = 0;pthread_join(pth, 0);return 0;}/*** @description: 删除文件* @param {*}char *file_name 被删除源文件* @return {*}*/int file_deleteFile(char *file_name){char szExcueCommand[150] = {0};if(!file_name) return -1;sprintf(szExcueCommand,"rm -r %s",file_name);system(szExcueCommand);return 0;}/*** @description: 获取文件大小* @param {*}* @return {*}*/int getFileSize(char *file_name){struct stat buf = {0};stat(file_name, &buf);return buf.st_size / 1024;}/*** @description: 压缩数据库视频文件,将视频文件和描述.txt文件一同压缩* @param {ST_VIDEO_DB_DATA} stVideoDbData 视频数据库文件* @param {char} *videoFileName 被压缩的视频源文件地址* @param {char} *zipName 压缩后的ZIP包文件地址* @return {*}*/int file_compressVideoFile(ST_VIDEO_DB_DATA stVideoDbData, char *videoFileName){FILE *fp = NULL;struct tm timeinfo;char ch_event[10240] = "";char ch_temp[64] = "";char ZipCmd[128] = "";char Zip_Name[64] = "";char txtName[64] = "";char txt_file[4096] = "";char rm_txtfile[64] = "";char rm_zipfile[64]="";char ch_tmp[32] = "";int i;time_t startTime, endTime, eventTime[512];int ret;pthread_t pth;ST_GET_RATE stGetRate;// 生产txt说明文件GetFileName3(stVideoDbData.file_path, Zip_Name); //去除后缀名sprintf(txtName, "%s.txt", Zip_Name);fp = fopen(txtName, "at+");if(fp == NULL){return;}timeinfo.tm_year = stVideoDbData.stStartTime.year - 1900;timeinfo.tm_mon = stVideoDbData.stStartTime.month - 1;timeinfo.tm_mday = stVideoDbData.stStartTime.date;timeinfo.tm_hour = stVideoDbData.stStartTime.hour;timeinfo.tm_min = stVideoDbData.stStartTime.minute;timeinfo.tm_sec = stVideoDbData.stStartTime.second;startTime = mktime(&timeinfo);timeinfo.tm_year = stVideoDbData.stEndTime.year - 1900;timeinfo.tm_mon = stVideoDbData.stEndTime.month - 1;timeinfo.tm_mday = stVideoDbData.stEndTime.date;timeinfo.tm_hour = stVideoDbData.stEndTime.hour;timeinfo.tm_min = stVideoDbData.stEndTime.minute;timeinfo.tm_sec = stVideoDbData.stEndTime.second;endTime = mktime(&timeinfo);for(i = 0; i < stVideoDbData.event_cnt; i++){timeinfo.tm_year = stVideoDbData.stEventTime[i].year - 1900;timeinfo.tm_mon = stVideoDbData.stEventTime[i].month - 1;timeinfo.tm_mday = stVideoDbData.stEventTime[i].date;timeinfo.tm_hour = stVideoDbData.stEventTime[i].hour;timeinfo.tm_min = stVideoDbData.stEventTime[i].minute;timeinfo.tm_sec = stVideoDbData.stEventTime[i].second;eventTime[i] = mktime(&timeinfo);memset(ch_temp, 0, sizeof(ch_temp));sprintf(ch_temp, "%d", eventTime[i]);strcat(ch_temp, "#");strcat(ch_event, ch_temp);}flock(fp, LOCK_EX);sprintf(txt_file, "%d\n%s\n%d\n%s\n%s\n%d\n%d\n%s\n%d,", stVideoDbData.chn_id,stVideoDbData.descriptor,stVideoDbData.event_cnt,\stVideoDbData.file_name,stVideoDbData.file_path,stVideoDbData.record_time_len,endTime,ch_event,startTime);fputs(txt_file, fp);fflush(fp);flock(fp, LOCK_UN);// 关闭文件fclose(fp);fp = NULL;strncat(Zip_Name, ".zip", 5);//将压缩文件后缀名添加进去// 创建线程strcpy(stGetRate.file_name, videoFileName);strcpy(stGetRate.dir_name, Zip_Name);stGetRate.cb = g_cb;stGetRate.userPtr = g_userPtr;stGetRate.run_flag = 1;ret = pthread_create(&pth, NULL, get_frate_fmc, (void*)&stGetRate);if(ret < 0){printf("Create pthread for \'\' is Failed - %d!\n", ret);return -1;}// 删除原压缩文件sprintf(rm_zipfile, "rm -rf %s", Zip_Name);system(rm_zipfile);// 执行压缩指令sprintf(ZipCmd,"zip -1qj %s %s %s",Zip_Name,stVideoDbData.file_path,txtName);system(ZipCmd);// 删除已经压缩的txt说明文件sprintf(rm_txtfile,"rm -r %s",txtName);system(rm_txtfile);// 结束线程stGetRate.run_flag = 0;pthread_join(pth, 0);}/*** @description: 压缩日志文件夹* @param {char} *LogFileName* @return {*}*/int file_compressLogFile(char *LogFileName){int ret;pthread_t pth;ST_GET_RATE stGetRate;char Zip_Name[64] = "";char ZipCmd[128] = "";printf("LogFileName=%s\n",LogFileName);strcpy(Zip_Name,LogFileName);strncat(Zip_Name,".zip",5);printf("Zip_Name:%s\n",Zip_Name);// 创建线程strcpy(stGetRate.file_name, LogFileName);strcpy(stGetRate.dir_name, Zip_Name);stGetRate.cb = g_cb;stGetRate.userPtr = g_userPtr;stGetRate.run_flag = 1;printf("stGetRate.file_name:%s\n",stGetRate.file_name);printf("stGetRate.dir_name:%s\n",stGetRate.dir_name);ret = pthread_create(&pth, NULL, get_frate_fmc, (void*)&stGetRate);if(ret < 0){printf("Create pthread for \'\' is Failed - %d!\n", ret);return -1;}sprintf(ZipCmd,"zip -1rqj %s %s",Zip_Name,LogFileName);printf("ZipCmd:%s",ZipCmd);system(ZipCmd);// 结束线程stGetRate.run_flag = 0;pthread_join(pth, 0);}/** 从文件中读取一行内容 */#define FILEBUFFER_LENGTH 5000#define EMPTY_STR ""int file_get_file_line(char *result, char *fileName, int lineNumber){FILE *filePointer;int i=0;char buffer[FILEBUFFER_LENGTH];char *temp;memset(buffer,'\0',FILEBUFFER_LENGTH*sizeof(char));strcpy(buffer,EMPTY_STR);if((fileName==NULL)||(result==NULL)){return 0;}strcpy(result, "");if(!(filePointer=fopen(fileName,"rb"))){return 0;}while((!feof(filePointer))&&(i<lineNumber)){if(!fgets(buffer,FILEBUFFER_LENGTH,filePointer)){return 0;}i++;//差点又忘记加这一句了}/* printf("\n%d\n",sizeof(*result));if(strlen(buffer)>sizeof(*result))//不能够这么写,虽然fgets读取一行后会在末尾加上'\0',但是sizeof(result)得到的结果却是result本身类型的大小,所以不能够这么算。当静态数组传入函数时,在函数内部只能知道它是一个指针{return 0;}*/if(0!=fclose(filePointer)){return 0;}if(0!=strcmp(buffer,EMPTY_STR)){while(NULL!=(temp=strstr(buffer,"\n"))){*temp='\0';}while(NULL!=(temp=strstr(buffer,"\r"))){*temp='\0';}strcpy(result,buffer);}else{strcpy(result,EMPTY_STR);return 0;}return 1;}/*** @description: 视频文件解压缩* @param {ST_VIDEO_DB_DATA} *stVideoDbData* @param {char} *videoFileName* @param {char} *zipName* @return {*}*/int file_UncompressVideoFile(ST_VIDEO_DB_DATA *stVideoDbData, char *videoFileName, char *zipName){ST_VIDEO_DB_DATA *pstVideoDbData = NULL;char ch = '.';FILE *fp = NULL;char extension[64] = "";char unzip_cmd[64] = "";char line[1024] = "";char line_1[64] = "";char txt_filename[64] = "";char video_filename[64] = "";char txt_name[64] = "";char path_name[64] = "";int line_cnt;ST_VIDEO_Search stVideoSearch;int nSearchCnt;int i, ret;char *saveptr = NULL;struct tm *timeinfo = NULL;int nTime;char *p = NULL;char qq[64] = "";char rm_txtfile[64]="";ST_GET_RATE stGetRate;pthread_t pth;char *q = strrchr(zipName, ch); //strrchr从后往前获取,一直到'.'if(q==NULL)return -1;printf("%s\n",q);struct tm tm_time;if(!strcmp(q,".zip")){// 获取txt名称和video名称GetFileName2(zipName,txt_name);sprintf(txt_filename, "/msata/dr_video/%s.txt",txt_name);strcpy(stGetRate.file_name, zipName);strcpy(stGetRate.dir_name, "");stGetRate.cb = g_cb;stGetRate.userPtr = g_userPtr;stGetRate.run_flag = 1;// 创建线程ret = pthread_create(&pth, NULL, get_frate_fmc, (void*)&stGetRate);if(ret < 0){printf("Create pthread for \'\' is Failed - %d!\n", ret);return -1;}sprintf(unzip_cmd,"unzip -o -d /msata/dr_video/ %s", zipName);system(unzip_cmd);// 退出线程stGetRate.run_flag = 0;pthread_join(pth, 0);if((access(txt_filename,F_OK))!=-1){file_get_file_line(line, txt_filename, 1);stVideoDbData->chn_id=atoi(line);file_get_file_line(line, txt_filename, 2);strcpy(stVideoDbData->descriptor,line);file_get_file_line(line, txt_filename, 3);stVideoDbData->event_cnt=atoi(line);file_get_file_line(line, txt_filename, 4);strcpy(stVideoDbData->file_name,line);file_get_file_line(line, txt_filename, 5);strcpy(stVideoDbData->file_path,line);GetFileName2(stVideoDbData->file_path,extension);q = strrchr(stVideoDbData->file_path, ch); //strrchr从后往前获取,一直到'.'strcpy(qq,q);printf("%s %s\n",extension, qq);sprintf(stVideoDbData->file_path,"/msata/dr_video/%s%s",extension,qq);file_get_file_line(line, txt_filename, 6);stVideoDbData->record_time_len=atoi(line);file_get_file_line(line, txt_filename, 7);nTime = atoi(line);timeinfo = gmtime((time_t*)&nTime);stVideoDbData->stEndTime.year=timeinfo->tm_year+1900;stVideoDbData->stEndTime.month=timeinfo->tm_mon + 1;stVideoDbData->stEndTime.date=timeinfo->tm_mday;stVideoDbData->stEndTime.hour=timeinfo->tm_hour;stVideoDbData->stEndTime.minute=timeinfo->tm_min;stVideoDbData->stEndTime.second=timeinfo->tm_sec;file_get_file_line(line, txt_filename, 8);if(stVideoDbData->event_cnt != utils_string_parse_delimiter_count(line, '#'))return 0;for(i = 0; i < stVideoDbData->event_cnt; i++){if(i == 0){p = utils_string_parse_strtok_r(line, '#', &saveptr);} else {p = utils_string_parse_strtok_r(NULL, '#', &saveptr);}if(p == NULL){return 0;}nTime = atoi(p);timeinfo = gmtime((time_t*)&nTime);stVideoDbData->stEventTime[i].year = timeinfo->tm_year + 1900;stVideoDbData->stEventTime[i].month = timeinfo->tm_mon + 1;stVideoDbData->stEventTime[i].date = timeinfo->tm_mday;stVideoDbData->stEventTime[i].hour = timeinfo->tm_hour;stVideoDbData->stEventTime[i].minute = timeinfo->tm_min;stVideoDbData->stEventTime[i].second = timeinfo->tm_sec;}file_get_file_line(line, txt_filename, 9);nTime = atoi(line);timeinfo = gmtime((time_t*)&nTime);stVideoDbData->stStartTime.year=timeinfo->tm_year+1900;stVideoDbData->stStartTime.month=timeinfo->tm_mon + 1;stVideoDbData->stStartTime.date=timeinfo->tm_mday;stVideoDbData->stStartTime.hour=timeinfo->tm_hour;stVideoDbData->stStartTime.minute=timeinfo->tm_min;stVideoDbData->stStartTime.second=timeinfo->tm_sec;file_get_file_line(line, txt_filename, 10);stVideoDbData->audio_resample=atoi(line);file_get_file_line(line, txt_filename, 11);strcpy(stVideoDbData->file_path_sec,line);db_searchVideoDbData(stVideoSearch, &nSearchCnt, &pstVideoDbData);for(i = 0; i < nSearchCnt; i++){if(!strcmp(pstVideoDbData[i].file_name,stVideoDbData->file_name)){db_releaseVideoDbData();sprintf(rm_txtfile,"rm -r %s",txt_filename);system(rm_txtfile);return 1;}}db_addVideoDbData(*stVideoDbData);db_releaseVideoDbData();sprintf(rm_txtfile,"rm -r %s",txt_filename);system(rm_txtfile);return 0;}else return -1;}else{return -1;}}/*** @description:获取文件带.后缀名的两个函数* @param {constchar} *file_name 文件的名字* @param {char} *extension 得到的文件的后缀* @return*/void get_extension(const char *file_name,char *extension){int i = 0, length;length = strlen(file_name);while(file_name[i]){if(file_name[i] == '.')break;i++;}if(i<length)strcpy(extension, file_name+i+1);elsestrcpy(extension, "\0");}void get_extension_2(const char *file_name,char *extension){char ch = '.'; // .代表文件后缀的起始char *q = strrchr(file_name, ch); // 文件后缀名不能去掉.memcpy(extension,q,sizeof(q));}/*** @description:获取带后缀的文件名* @param {char} *filePath* @return {*}*/char *GetFileName1(char *filePath){// int len = strlen(filePath);char ch = '//'; // 其中一个反斜杠是转义字符char *q = strrchr(filePath, ch) + 1; // 注意这里要+1, 否则输出是:\filename.exereturn q;}/*** @description: 获取不带后缀不带路径的文件名* @param {char} *filePath* @param {char} *extension* @return {*}*/void GetFileName2(char *filePath,char *extension){int i = 0;int start, end;if(filePath == NULL || extension == NULL)return;while(filePath[i] != '\0'){if(filePath[i] == '/')start = i + 1;if(filePath[i] == '.'){end = i;break;}i++;}strncpy(extension, filePath+start, end-start);}/*** @description:获取不带后缀带路径的文件名* @param {char} *filePath* @return {*}*/void GetFileName3(char *filePath,char *extension){int i = 0;if(filePath == NULL || extension == NULL)return;while(filePath[i] != '\0'){if(filePath[i] == '.')break;i++;}strncpy(extension, filePath, i);}/***为了清楚,单独写一个子函数实现判断两个字符串匹配*/char *match( char *str, char *want){while( *want != NULL)if( *str++ != *want++ )return NULL;return str;}/***删除子串函数*/int del_substr( char *str, char *substr ){char *next;char *find = str;/***保证被操作字符串不为空***/while( *find != NULL){next = match( find, substr );if( next != NULL)break;find++;}/***到达源字符串文件尾的时候,说明没有子串*/if( *find == NULL)return -1;/***被删除子串之后的字符复制操作*/while( *find++ = *next++ );return 0;}

Qt里面使用回调函数在界面显示拷贝文件的进度

static void progress(int progress, void *userPtr){int calc_progress;QString progress_int;file_select *file_Select = (file_select*)userPtr; //将传递过来的指针转换calc_progress=(file_Select->progress_count*100 + progress ) / file_Select->All_selectcont;progress_int=QString::number(calc_progress)+"%";file_Select->ui->label_4->setText(progress_int); //设置Qt界面中的labelusleep(2);QPalette palette;palette.setColor(QPalette::Text,Qt::white);file_Select->ui->progressBar->setPalette(palette);file_Select->ui->progressBar->setStyleSheet("QProgressBar{background:rgb(136,136,136);} QProgressBar::chunk{background:rgb(0,0,136)}");file_Select->ui->progressBar->setValue(calc_progress);usleep(100);//file_Select->ui->progressBar->setStyleSheet("");file_Select->ui->progressBar->setValue(calc_progress);}file_select::file_select(QWidget *parent) :QWidget(parent),ui(new Ui::file_select){ui->setupUi(this);ui->tableWidget->viewport()->installEventFilter(this); //注册事件过滤器ui->tableWidget->verticalScrollBar()->installEventFilter(this);ui->tableWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);ui->tableWidget->horizontalHeader()->setStretchLastSection(false);ui->tableWidget->setColumnWidth(0, 60);ui->tableWidget->setColumnWidth(1, 60);ui->tableWidget->setColumnWidth(2,300);ui->tableWidget->setColumnWidth(3,200);ui->tableWidget->setColumnWidth(4,230);ui->tableWidget->setRowHeight(0,100);ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); //ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); //file_setCallback(progress,this); //使用c库中的函数,设置回调函数,这是一个QT的界面,所以可以用this指针代替this->len=0;this->dr_video=1;this->All_selectFlag = 0;this->udiskFlag=0;this->query_startVideo=0;this->query_endVideo=0;this->query_videoKeyword=0;QPalette palette;palette.setColor(QPalette::Text,Qt::black);this->ui->progressBar->setPalette(palette);progress_count=0;}

【领QT开发教程学习资料,点击下方链接莬费领取↓↓,先码住不迷路~】

点击这里:「链接」

标签: #c语言文本文件读取数据 #c如何从文件中读取数据 #用c实现一个字符串拷贝函数的过程 #strtok_r头文件 #多文件c编译