#include
#include
#include
#include
using namespace std;
void csvline_populate(vector &record, const string& line, char delimiter);
int main(int argc, char *argv[])
{
vector row;
string line;
ifstream in("input.csv");
if (in.fail()) { cout << "File not found" <
while(getline(in, line) && in.good() )
{
csvline_populate(row, line, ',');
for(int i=0, leng=row.size(); i
cout << row[i] << "\t";
cout << endl;
}
in.close();
return 0;
}
void csvline_populate(vector &record, const string& line, char delimiter)
{
int linepos=0;
int inquotes=false;
char c;
int i;
int linemax=line.length();
string curstring;
record.clear();
while(line[linepos]!=0 && linepos < linemax)
{
c = line[linepos];
if (!inquotes && curstring.length()==0 && c=='"')
{
//beginquotechar
inquotes=true;
}
else if (inquotes && c=='"')
{
//quotechar
if ( (linepos+1
{
//encountered 2 double quotes in a row (resolves to 1 double quote)
curstring.push_back(c);
linepos++;
}
else
{
//endquotechar
inquotes=false;
}
}
else if (!inquotes && c==delimiter)
{
//end of field
record.push_back( curstring );
curstring="";
}
else if (!inquotes && (c=='\r' || c=='\n') )
{
record.push_back( curstring );
return;
}
else
{
curstring.push_back(c);
}
linepos++;
}
record.push_back( curstring );
return;
}http://www.zedwood.com/article/112/cpp-csv-parser
6.2.4 CSV文件的读取
CSV即Comma Separated Values(以逗号分隔的值),这种文件格式经常用来作为不同程序之间的数据交互的格式。具体文件格式如下。
每条记录占一行。
记录间的值以逗号为分隔符。
逗号前后的空白字符会被忽略。
如果值中包含逗号、换行符、空格、双引号,则该值必须用双引号引起来。
值中的双引号用两个双引号表示。
如下是一段标准的CSV数据,它来自于某次科学实验的采集记录:1993,124,0,13.9,11.2,7.9,5.2,3.7,2.8,2.7,3.0,0.0,0.0
1993,125,1,14.2,11.4,8.0,5.3,3.8,2.8,2.7,3.0,0.0,0.0
1993,126,2,14.4,11.7,8.2,5.4,3.9,2.8,2.7,3.0,0.0,0.0
1993,127,3,13.7,11.1,7.7,5.1,3.6,2.6,2.6,2.9,0.0,0.0
1993,128,4,12.9,10.4,7.2,4.7,3.3,2.4,2.4,2.8,0.0,0.0
1993,129,5,12.1,9.7,6.6,4.2,2.9,2.2,2.3,2.7,0.0,0.0
1993,130,6,12.3,9.9,6.8,4.3,3.0,2.2,2.3,2.7,0.0,0.0
1993,131,7,12.0,9.6,6.6,4.2,2.9,2.1,2.2,2.7,0.0,0.0
1993,132,8,12.6,10.1,7.0,4.5,3.1,2.2,2.3,2.7,0.0,0.0
将该段数据保存为某个文件,如:test.csv。Microsoft Excel支持CSV文件格式,图6-12示出在Microsoft Excel中打开test.csv的情形。
(点击查看大图)图6-12 在Microsoft Excel中打开test.csv
现在动手
下面我们使用文件流来实现一个CSV文件的读取程序。
选择【Win32】→【Win32项目】→【控制台程序】命令,创建CsvParser。
创建CRow类,它用来描述每一个行的记录。该类实际上是一个CStringArray的代理类:classCRow
{
private:
CStringArray * _row;
public:
CRow(CStringArray * row);
intgetColumnCount(void);
CString getColumn(inti);
};
CRow::CRow(CStringArray * row)
{
_row = row;
}
intCRow::getColumnCount(void)
{
return_row->GetCount();
}
CString CRow::getColumn(inti)
{
return_row->GetAt(i);
}
创建CSheet类,它用来描述一张表格:classCSheet
{
private:
CTypedPtrArray _rows;
public:
CSheet(void);
~CSheet(void);
intloadFrom(ifstream & in);
intgetRowCount(void);
CRow getRow(inti);
};
CSheet::CSheet()
{
}
CSheet::~CSheet()
{
for(inti = 0; i
{
delete_rows.GetAt(i);
}
}
intCSheet::loadFrom(ifstream & in)
{
intlines = 0;
while(!in.eof())
{
//读取其中的一行
charline[256] = {0};
in.getline(line, 255);
CString s = line;
//空白行,跳过
if(s.IsEmpty())
continue;
//#为注释标记,跳过
if(s[0] =='#')
continue;
CStringArray *pRow =newCStringArray();
inti = 0;
CString token = s.Tokenize(_T(",\t"), i);
while(token != _T(""))
{
pRow->Add(token);
token = s.Tokenize(_T(",\t"), i);
}
_rows.Add(pRow);
lines++;
}
returnlines;
}
intCSheet::getRowCount(void)
{
return_rows.GetCount();
}
CRow CSheet::getRow(inti)
{
returnCRow(_rows.GetAt(i));
}
修改主程序如下:#include "stdafx.h"
#include "sheet.h"
#include
#include
usingnamespacestd;
intmain()
{
CSheet sheet;
//打开csv文件
ifstream in("test.csv");
//加载至CSheet
sheet.loadFrom(in);
for(inti = 0; i
{
_tprintf(_T("[%02d] "), i);
//获取指定行
CRow row = sheet.getRow(i);
for(intj = 0; j
{
//获取指定列
CString s = row.getColumn(j);
_tprintf(_T("%s/"), s);
}
_tprintf(_T("\r\n"), i);
}
return0;
}
运行结果如图6-13所示。
(点击查看大图)图6-13 运行结果
当然,本程序考虑的情况还是不够完善的,希望读者能够结合该实例完善CSV文本文件的解析。
http://book.51cto.com/art/200908/145788.htm