读取CSV每一行,每一行内容在解析时可以分为2种情况:1.没扫描到" 2.扫描到"
情况1:
直接通过截取内容中的,来分列。例如行内容为: 姓名,年龄,编号 。则可以分为3列
姓名 |
年龄 |
编号 |
情况2:
扫描行内容,当扫描到内容的第一个",去掉该",接着扫描
<1>之后扫描到""则输出"
<2>其他内容按照原内容输出
<3>当扫描到单个符号"("之后没有紧接着")则去掉这个",该列扫描完毕。
最后输出的内容为该列的值。
例如内容为: """,","," 。则可以分为2列
", |
, |
头文件:
1 #include<iostream> 2 #include<fstream> 3 #include<string> 4 using namespace std; 5 6 class CCsv 7 { 8 public: 9 //构造函数 10 CCsv(void); 11 12 /******************************************************************* 13 ** 函数名: Csv_IsCsvFile 14 ** 函数描述: 判断文件是否是csv文件 15 ** 参数: [in] strFileName: csv文件名 16 ** 返回: true,是csv文件;false,不是csv文件 17 *******************************************************************/ 18 bool Csv_IsCsvFile(const string &strFileName); 19 20 /******************************************************************* 21 ** 函数名: Csv_ReadFile 22 ** 函数描述: 读取CSV文件,并解析内容存放到vvStr,并判断csv文件是否规范 23 ** 参数: [in] pFileName: 该csv文件名 24 ** [in] vvStr: 用于存放解析内容 25 ** 返回: true,解析成功;false,解析失败 26 *******************************************************************/ 27 bool Csv_ReadFile(const char* pFileName, vector<vector<string> > &vvStr); 28 29 /******************************************************************* 30 ** 函数名: Csv_AnalysisCsvLine 31 ** 函数描述: 解析CSV文件的一行内容,并把该行解析内容放入vvStr 32 ** 参数: [in] strContent: CSV文件的一行内容 33 ** [in] vvStr: 用于存放解析内容 34 ** 返回: 35 *******************************************************************/ 36 void Csv_AnalysisCsvLine(const string & strContent, vector<vector<string> > &vvStr); 37 38 /******************************************************************* 39 ** 函数名: Csv_ShowCsvContent 40 ** 函数描述: 输出vvStr所存放的csv解析内容 41 ** 参数: [in] vvStr: 用于存放解析内容 42 ** 返回: 43 *******************************************************************/ 44 void Csv_ShowCsvContent(vector<vector<string> > &vvStr); 45 46 //析构函数 47 ~CCsv(void); 48 private: 49 50 };
主程序:
1 #include "stdafx.h" 2 #include <iostream> 3 #include <string> 4 #include <vector> 5 #include <algorithm> 6 #include "modCsv.h" 7 using namespace std; 8 9 int g_rows = 0; //记录列下标 10 const char cQuote = '"'; //定义引号常量 11 const char cComma = ','; //定义逗号常量 12 13 //CCsv构造函数 14 CCsv::CCsv(void) 15 { 16 17 } 18 19 //CCsv析构函数 20 CCsv::~CCsv(void) 21 { 22 23 } 24 25 //判断文件是否为csv文件 26 //strFileName为文件名 27 bool CCsv::Csv_IsCsvFile(const string &strFileName) 28 { 29 //csv文件最少字符为a.csv,所以当文件名小于5,该文件就不是csv文件 30 if (strFileName.length()<5) 31 { 32 cout<<"该文件不是csv文件!"<<endl; 33 return false; 34 } 35 36 string strFileFormat = strFileName.substr(strFileName.length()-4,4);//截取文件的后缀名 .csv 37 //将文件后缀变为小写 38 transform(strFileFormat.begin(),strFileFormat.end(),strFileFormat.begin(),::tolower); 39 40 //判断文件名是否是csv文件 41 if (1 == strFileFormat.compare(".csv")) 42 { 43 cout<<"该文件不是csv文件!"<<endl; 44 return false; 45 } 46 47 return true; 48 } 49 50 //读取并解析CSV文件,并判断csv文件是否规范 51 //pFileName为该csv文件名, vvStr为用于存放解析内容的变量 52 bool CCsv::Csv_ReadFile(const char* pFileName, vector<vector<string> > &vvStr) 53 { 54 if (pFileName == NULL) 55 { 56 return false; 57 } 58 //创建输入流 59 ifstream inCsv(pFileName, ios::in); 60 61 //判断打开文件是否成功 62 if (!inCsv) 63 { 64 cout<<"打开文件失败! "; 65 return false; 66 } 67 68 //读文件 69 while (!inCsv.eof()) 70 { 71 string lineContent; 72 inCsv>>lineContent; //行内容暂存到lineContent 73 //解析该行内容 74 Csv_AnalysisCsvLine(lineContent,vvStr); 75 } 76 77 size_t size = vvStr[0].size();//初始每行列数 78 //循环判断每行的列数是否一样 79 for (vector<vector<string> >::iterator vvIt = vvStr.begin(); vvIt != vvStr.end(); ++ vvIt) 80 { 81 g_rows++; 82 if ((*vvIt).size() != size) 83 { 84 cout<<"该csv文件格式不符合规范:第"; 85 cout<<g_rows<<"行有"<<(*vvIt).size()<<"列,而第一行有"<<size<<"列"<<endl; 86 break; 87 } 88 } 89 90 //显示解析内容 91 Csv_ShowCsvContent(vvStr); 92 return true; 93 } 94 95 //解析CSV文件的一行内容 96 void CCsv::Csv_AnalysisCsvLine(const string & strContent, vector<vector<string> > &vvStr) 97 { 98 //string *pStrContent = &strContent; 99 string strRowContent = "";//初始化列内容为空 100 vector<string> vRowContent ;//临时vector ,用于最后存入vvStr 101 102 //扫描整行内容 103 for(size_t i = 0; i < strContent.size(); i++)// i 为size_t而不是int,是由于strContent.size()返回的是unsigned int 104 { 105 //当扫描到" ,表示一串字符开始 106 if (strContent[i] == cQuote) 107 { 108 while (i < strContent.size()) 109 { 110 i++; 111 if (strContent[i] ==cQuote) 112 { //如果内容为"" ,表示输出转义字符" 113 if (strContent[i+1] == cQuote) 114 { 115 strRowContent += cQuote; 116 i = i + 1; //指针往下 117 } 118 //"后面没有紧接着",表示一列结束,break跳出循环 119 else 120 { 121 break; 122 } 123 124 } 125 else 126 { 127 strRowContent += strContent[i]; //该字符添加入列内容 128 } 129 } 130 //当扫描结束还是扫描不到"(字符串结束符),则该行的"没有成对存在,不符合csv规则 131 if (strContent[i] == '