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<<"打开文件失败!
";
 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] == '')
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 }

新手刚上路,代码还有很多缺陷仍在改进中。。。。。

原文地址:https://www.cnblogs.com/qq42425328/p/zhen.html