CSV简单解析与排序输出
读取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<<"打开文件失败!\n"; 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] == '\0') 132 { 133 cout<<"该csv文件格式不符合规范:第"<<(vvStr.size()+1)<<"行的\"不匹配"<<endl; 134 } 135 } 136 //当前字符为',' ,表示一列结束 137 else if (strContent[i] == cComma) 138 { 139 //把strRowContent存放的列的内容放入vRowContent 140 vRowContent.push_back(strRowContent); 141 strRowContent = ""; 142 } 143 else 144 { 145 strRowContent += strContent[i]; //该字符添加入列内容 146 } 147 } 148 //把strRowContent存放的列的内容放入vRowContent 149 vRowContent.push_back(strRowContent); 150 //把该行所有列的内容村放入vvStr 151 vvStr.push_back(vRowContent); 152 } 153 154 //输出 vector<vector<string> > &vvStr 所存放的csv解析内容 155 void CCsv::Csv_ShowCsvContent(vector<vector<string> > &vvStr) 156 { 157 //用迭代方式输出 vector<list<string>> vlStr 所存放的csv解析内容 158 for (vector<vector<string> >::iterator vvIt = vvStr.begin(); vvIt != vvStr.end(); ++ vvIt) 159 { 160 for (vector<string>::iterator vIt = (*vvIt).begin(); vIt != (*vvIt).end(); ++ vIt) 161 { 162 cout<<*vIt<<" "; 163 } 164 cout<<endl; 165 } 166 } 167 168 bool SortMethod(const vector<string> &vStr1, const vector<string> &vStr2)//本函数的参数的类型一定要与vector中元素的类型一致 169 { 170 return vStr1[g_rows-1] < vStr2[g_rows-1];//升序排列 171 } 172 173 int main(void) 174 { 175 CCsv csv;//定义csv对象 176 string strFileName = "in.csv";//定义csv的文件名 177 178 //判断文件是否为csv文件,若不是直接结束程序 179 if(!csv.Csv_IsCsvFile(strFileName)) 180 { 181 return 0; 182 } 183 184 const char* pFileName = &strFileName[0]; //定义要解析的文件名 185 vector<vector<string> > vvStr ; //用于存放解析内容 186 187 cout<<"FileName:"<<pFileName<<endl; 188 189 //读取并解析pFileName到vvStr中 190 csv.Csv_ReadFile(pFileName, vvStr); 191 192 cout<<"输入需要排序的列("; 193 //用迭代的方式输出列的可选排序项 194 g_rows = 0; 195 for (vector<string>::iterator vIt = vvStr[0].begin(); vIt != vvStr[0].end(); ++vIt) 196 { 197 cout<<++g_rows<<"."<<*vIt<<" "; 198 } 199 cout<<"):"; 200 201 //输入需要排序的列 202 cin>>g_rows; 203 204 //排序函数 205 sort((vvStr.begin()+1),vvStr.end(),SortMethod); 206 207 //显示排序后的csv内容 208 csv.Csv_ShowCsvContent(vvStr); 209 210 return 1; 211 }
新手刚上路,代码还有很多缺陷仍在改进中。。。。。