#include <tchar.h>
#include <afxtempl.h>
#include <stdio.h>
#include <string.h>
#ifndef CStringA
#define CStringA CString
#endif //CStringA
//解析CSV行数据核心代码
//chLine 输入行
//szDataArray 子项解析输出
//返回值:子项个数
int AnalysCSVDataLine(LPCSTR chLine, CStringArray &szDataArray)
{
ASSERT(chLine != NULL);
//先清理输出项
szDataArray.RemoveAll();
//子项状态
enum _tagItemType_t
{
_Invalid_Item, //无效项
_Comma_Item, //逗号分隔项
_Quota_Item, //引号分隔项
};
//子项状态初始化为无效
_tagItemType_t eItem = _Invalid_Item;
//子项数据字符缓存区
CStringA szSubData;
//行长度
int iLineLen = (int)strlen(chLine);
//解析子项
for(int iPos=0; iPos<iLineLen; )
{
//读取两个字符
char c0 = chLine[iPos+0];
char c1 = (iPos+1 <iLineLen)? chLine[iPos+1]:0;
//插入子项?
int iInsertFlag = 0;
//依据子项状态处理
switch(eItem)
{
case(_Invalid_Item): //无效
{
szSubData.Empty(); //先清空子项
if(c0 == '\"') //引号起始
{
eItem = _Quota_Item; //转为引号分隔
iPos += 1; //跳过"
}
else
{
eItem = _Comma_Item; //逗号分割符
}
break;
}
case(_Quota_Item): //引号分隔
{
if(c0 == '\"' && c1 == '\"') //"" 遇两个引号
{
szSubData += "\""; //数据添加一个"
iPos += 2; //跳过""
}
else if(c0 == '\"' && (c1==',' || c1=='\n' || c1=='\0')) //",或 "\0 遇行结束符
{
iInsertFlag = 2; //插入子项
}
else //正常数据
{
szSubData += c0; //追加数据
iPos++; //跳到下一字符
}
break;
}
case(_Comma_Item): //逗号风格符
{
if(c0==',' || c0=='\n' || c0=='\0') //逗号或行结束
{
iInsertFlag = 1; //插入子项
}
else //正常数据
{
szSubData += c0; //追加数据
iPos++; //跳到下一字符
}
}
}
//插入子项
if(iInsertFlag)
{
szDataArray.Add(szSubData); //添加子项
eItem = _Invalid_Item; //等待下一项
iPos += iInsertFlag; //跳过长度
}
}
//返回子项个数
return (INT)szDataArray.GetSize();
}
int AnalsysCSVDataFile(LPCTSTR szFile,
CTypedPtrArray <CPtrArray, CStringArray *> &szDataArray)
{
FILE *fp = NULL;
if((fp = _tfopen(szFile, _T("rt"))) != NULL)
{
while(!feof(fp))
{
//行字符缓存区
CHAR chLine[8192];
memset(chLine, 0, sizeof(chLine));
//读行
if(fgets(chLine, sizeof(chLine), fp) == NULL)
break;
//解析行
CStringArray szDataLines;
if(AnalysCSVDataLine(chLine, szDataLines) > 0)
{
//追加行
CStringArray *pStrA = new CStringArray;
pStrA->Copy(szDataLines);
szDataArray.Add(pStrA);
}
}
//关闭文件
fclose(fp);
}
return (INT)szDataArray.GetSize();
}
//调用示例
void CDlg3Dlg::OnButton1()
{
//打开文件
CFileDialog dlg(TRUE, _T(".csv"), NULL, 0,
_T("csv files(*.csv)|*.csv||"), this);
if(dlg.DoModal() == IDOK)
{
//解析文件
CTypedPtrArray <CPtrArray, CStringArray *>sData;
AnalsysCSVDataFile(dlg.GetPathName(), sData);
//输出内容
for(INT_PTR iLine=0; iLine<sData.GetSize(); iLine++)
{
CStringArray *sLine = sData.GetAt(iLine);
INT iMaxItem = (INT)sLine->GetSize();
TRACE(_T("Line%d==>(%d)==>"), iLine, iMaxItem);
for(INT iItem=0; iItem<iMaxItem; iItem++)
{
CString sItem = sLine->GetAt(iItem);
TRACE(_T("[%s]"), sItem);
}
TRACE(_T("\n"));
}
//结束清理
while(sData.GetSize() > 0)
{
delete sData.GetAt(0);
sData.RemoveAt(0);
}
}
}
//测试用csv文件内容
1,"""2""","3,ABC",4,"""""",",",""",""",,"aaa"",""bbb"
1,"""2""","3,ABC",4,"""""",",",""",""",,"aaa""??bbb"""
1,"""2""","3,ABC",4,"""""",",",""",""",,"aaa""??bbb"""
//调试输出
Line0==>(9)==>[1]["2"][3,ABC][4][""][,][","][][aaa","bbb]
Line1==>(9)==>[1]["2"][3,ABC][4][""][,][","][][aaa"??bbb"]
Line2==>(9)==>[1]["2"][3,ABC][4][""][,][","][][aaa"??bbb"]