工作中的一点遐想
今天工作要整到银联文件,因为初次接触银联收单,对文件格式不清楚,其实就是将银联所给的文件导入到数据库中而已。看以前同事写的代码惨不忍睹。不知道哪位仁兄写的代码如下:memcpy(sDbRecord+47,sFileRecord+106,6); memcpy(sDbRecord+174+8,sFileRecord+113,4); memcpy(sDbRecord+179+8,sFileRecord+118,8); sDBRecod和SFIleRecord都是char*型,他的意思是从文件读一行到sFileRecord中然后copy其中的某个字段到sDbRecord中,比如文件中的第106个起6个字节是流水号,对应数据库结构中的偏移47个字节。再通过类型强转换成对应的数据结构。memcpy ((char *)&htCupTxn, sDbRecord, sizeof (htCupTxn));htCupTxn是一个数据结构与表结构对应。看得我郁闷不已。你连字节段都数得这么清楚了,结构体都已经建好了,干嘛不copy到结构体中。发完牢骚,要新增加一个银联文件,我肯定是不能这么干的了,真不想被后人骂。后来看银联标准,文件格式无非两种,定长后补空格型和带登即相许和符型的。这是我对带分隔符的文件处理的示例代码。在这里我用了宏,在现在开发中我还是比较喜欢用宏的,一方面如果真的要改什么的话,可以改一个宏就可以,方便了以后需求的改动。而且我认为一个函数超过一个屏幕的高度,就应该精简了。除非不能精简.
typedef struct
{
char member1[8+1];
char member2[48+1];
}stStructTest;
;
#define STRUCT_MEMBER_LENGTH(x,y,t) sizeof((x).y)/sizeof(t) -1
#define STRUCT_MEMBER_CUTZERO(x,y) *(((x).y) + STRUCT_MEMBER_LENGTH(x,y,char))=0
#define STRUCT_MEMBER_FILL(x,y,p) memcpy((x).y,p,STRUCT_MEMBER_LENGTH(x,y)) \
STUCT_MEMBER_CUTZERO(x,y)
#define STRUCT_MEMBER_MIN_STRING(x,y,p) min(strlen(p),STRUCT_MEMBER_LENGTH(x,y,p))
#define STRUCT_MEMBER_STRCPY(x,y,p) memcpy((x)->y,p,STRUCT_MEMBER_MIN_STRING(x,y,p)
static const char* g_delit= " ,|:\n";
//过虑一行最前面的字符
char * filter_froward(char *line,char c){
char *p = line ;
while (*p == c && *p != NULL)
{
p++;
}
return p ;
}
inline void getMemString(stStructTest*pData,int i,const char*p){
switch(i){
case 0:
STRUCT_MEMBER_STRCPY(pData,member1,p);
break ;
case 1:
STRUCT_MEMBER_STRCPY(pData,member2,p);
break ;
default:
break ;
}
}
//将一行内容对应到数据结构休整中
int format(char* line,stStructTest *ptTest){
char *p =line;
stStructTest test;
int i = 0 ;
if(*p == NULL || p == NULL)return -1;
p = filter_froward(line,' ') ;
if(p == NULL ){
return -3;
}
p = strtok(p,g_delit);
if(p == NULL)
return -4;
do{
getMemString(&test,i,p);
i ++ ;
}while(p = strtok(NULL,g_delit));
if( i == 2){
memcpy(ptTest,&test,sizeof(test));
return 0
}
return -1;
}
int file_format(const char*pFileIn,const char*pFileOut){
FILE *in ;
unigned int i;
char line[1024] ;
stStructTest test ;
in = fopen(pFileIn,"r") ;
if( in == NULL){
return -1 ;
}
memset(line, 0, sizeof(line)) ;
i = 0 ;
while(fgets(line,sizeof(line),in) != NULL){
i ++ ;
if(0 == format(line,&test) ){
insertToDbs(&test);
}
memset(line, 0, sizeof(line)) ;
}
fclose(in);
return i ;
}
到于定长格式的就更好搞定。通过宏就行了。本来想有没有办法不要每次格式变了就得修改代码的,后来想了想还是不行,没办法为了好看,结构体还是得定义的。
就通过switch case 吧。
第一次发博客,代码没有测试,估计差不多吧。但是这个代码风格,我觉得那位老兄应该下地域。有时间数字节数何不自定义数据结构呢。更何况插入到数据的那个表现成
的就可以用。哎!!!
浙公网安备 33010602011771号