C++的文件解析

来源:互联网 发布:js的形参和实参 编辑:程序博客网 时间:2024/06/05 15:16

工作中,我们常常会解析文件,特别是unix下的C++编程。以我目前的工作来说,我发现大的系统后台的处理,大多都是文件的处理,而这些处理的代码,大多是C++,C这些语言来写的。而像java这种,只用来做前台页面展示时用到。文件处理基本就不用。

下面我就把目前我常用的文件解析的C++后台代码贴出来,大家一起探讨学习。

/*

**函数名:ProcessFileAlert(const char *pchFileName),解析文件的入口。

**参数说明:pchFileName,被解析文件的全路径。

**返回值:解析完成返回1,文件无法打开或无法移动文件返回-1,

*/

int ProcessFileAlert(const char *pchFileName)
{

//char *pch;
char pchFileNameWithPath[MAXSTRINGLENGTH];
memset(pchFileNameWithPath,0,sizeof(pchFileNameWithPath));

int iRetFlag; 
int iSetFlag;
int iOverlyFlag;

//找到文件开始处理

//这句话是因为我当前的业务决定了我的文件名和文件前面的路径拼接起来组成全路径,用的时候大家可以直接传递文件全路径给函数。
sprintf(pchFileNameWithPath, "%s/%s\0", m_pConfigInfo.m_chInputPath, pchFileName);

//打开文件失败

if (!OpenFile(pchFileNameWithPath))
{
  printf("OpenFile fail!\n");
  return -1;
}

//不断获取文件下一条记录。

while ((iRetFlag = GetNextCdr164()) > 0)
{
  continue;
}

//关闭文件

CloseFile();

//移动文件,主要是备份之用。大家可以根据需求来考虑要不要这步
if (!RemoveRawCdrFile(pchFileNameWithPath, m_pConfigInfo.m_chBackupPath))
{
  printf("RemoveRawCdrFile fail!\n");
  return -1;
}

return 1;
}


/*
* Function Name :OpenFile
* Description :打开文件
* Input param :
**  mpchFileNameWithPath:文件名带路径
* Returns  :打开成功,返回true,否则false
*/
bool OpenFile(const char *mpchFileNameWithPath)
{
char *pchFileName;
   /*初始化文件指针*/
m_FileStream = NULL;
//判断文件是否可读
if (NULL == (m_FileStream = fopen(mpchFileNameWithPath, "r" )))
{
  return false;
}
//pchFileName = strrchr(pchFileNameWithPath, '/');
/*文件名*/
//strcpy(m_chFileName, pchFileName + 1);

return true;

}

/*
* Function Name :RemoveRawCdrFile
* Description :移去处理过的文件,主要是用作备份。
* Input param :
**  mpchFileNameWithPath:文件名带路径
**  pchBackupPath:备份路径
* Returns  :true表示处理成功,其它失败
*/
bool  RemoveRawCdrFile(const char *mpchFileNameWithPath, const char *pchBackupPath)
{
char chBackupFile[MAXSTRINGLENGTH];
char *pch;

/*需要备份?*/
if (*pchBackupPath != 0)
{
  pch = (char *)strrchr(mpchFileNameWithPath, '/') + 1;
  sprintf(chBackupFile, "%s/%s", pchBackupPath, pch);
  unlink(chBackupFile);
  if (link(mpchFileNameWithPath, chBackupFile) == -1)
  {
    printf("link file err!\n");
   return false;
  }
 
}

if (unlink(mpchFileNameWithPath) == -1)
{
  printf("unlink file err!\n");
  return false;
}

return true;
}

/////////////////////////////////////////////////////////////////////////
// 函数名:GetNextCdr
// 作  用:从原始文件取下一条文件记录
// 参  数:无
// 返回值:0--文件末尾, -1--读文件出错
//         1--成功
// 修  改:
/////////////////////////////////////////////////////////////////////////
int GetNextCdr164()
{
//sprintf(m_LogCdrs.FileOffSet, "%08X", ftell(m_FileStream));
memset(m_chCdrBuf, 0, sizeof(m_chCdrBuf));
//取得原始文件中第一行的记录
fgets((char *)m_chCdrBuf, 1024, m_FileStream);

//遇到文件尾
if (feof(m_FileStream))
{
  return 0;
}

//遇到读文件错误
else if (ferror(m_FileStream))
{
  return -1;
}
ExtractCdr164();
arr_nums++;
return 1;
}

/////////////////////////////////////////////////////////////////////////
// 函数名:ExtractCdr164
// 作  用:取出原始文件记录中各个域的值
// 参  数:无
// 返回值:true--成功
// 修  改:
/////////////////////////////////////////////////////////////////////////
void ExtractCdr164()
{
m_pchPlace = m_chCdrBuf;
  //取第一行第一个字段
GetOneField164(m_AlertFile[arr_nums].s_chFlag, sizeof(m_AlertFile[arr_nums].s_chFlag)-1);
//取第一行第二个字段
GetOneField164(m_AlertFile[arr_nums].s_chDesc, sizeof(m_AlertFile[arr_nums].s_chDesc)-1);
//取第一行第三个字段
GetOneField164(m_AlertFile[arr_nums].s_chStartTime, sizeof(m_AlertFile[arr_nums].s_chStartTime)-1);

//取第一行第四个字段

GetOneField164(m_AlertFile[arr_nums].s_chEndTime, sizeof(m_AlertFile[arr_nums].s_chEndTime)-1);

//取第一行第五个字段

GetOneField164(m_AlertFile[arr_nums].s_chDetail, sizeof(m_AlertFile[arr_nums].s_chDetail)-1);

//取第一行第六个字段

GetOneField164(m_AlertFile[arr_nums].s_chEvent, sizeof(m_AlertFile[arr_nums].s_chEvent)-1);

/////////////////////////////////////////////////////////////////////////
// 函数名:GetOneField164
// 作  用:取一个字段(字段间有‘,’分隔)
// 参  数:无
// 返回值:无
// 修  改:
/////////////////////////////////////////////////////////////////////////
void GetOneField164(char * chDest, int iLength)
{
char chTemp[100];
int i = 0;
if (chDest == NULL)
{
  return ;
}
memset(chTemp, 0, sizeof(chTemp));
while((*m_pchPlace != ',') && (*m_pchPlace != '\n') && (*m_pchPlace != 0) )
{
  chTemp[i] = *m_pchPlace;
  i ++;
  m_pchPlace ++;
}
if (*m_pchPlace == ',')
{
  m_pchPlace ++;
}
if (strlen(chTemp) <= iLength)
{
  strcpy(chDest, chTemp);
}
}

上例中S_AlertFile结构如下:

struct S_AlertFile
{
char  s_chFlag[50+1]; //名称
char  s_chDesc[100+1]; //名称描述
char  s_chStartTime[25+1]; //开始时间
char  s_chEndTime[25+1]; //结束时间
char  s_chDetail[100+1];//详细描述
char  s_chEvent[100+1];//事件
};

至此,对一种特定的文件的解析并把解析结构存入结构中。很明显,上例中的代码中有个别变量或数组并没有申明就在使用。这是因为这些代码原本是在类中封装的,类中的成员在这里就不贴出来了,大家仁者见仁。

以上被解析的文件适用于unix文件,其文件格式适用于如下:

 

unix下,每行自己录用逗号分隔,当然也可以是其他的诸如: | 等这样的符号,即便如此,你只需要在代码中更改很少的部分。unix下每行记录会有\r\n结尾。这也就解释了GetOneField()函数中为何要那么处理了。

原创粉丝点击