对于 Excel 生成的 .csv 文件的读取
首先我么来看一下生成的结果:
对于这样的数据,让我们来看看他们究竟是怎么解析的吧!
我们先看一下我们需要用到的配置文件,也就是我这里使用到的 Book1.csv
注意:红色区域圈住的地方要注意,你使用 Excel 导出后,然后用 Notepad++ 将其保存的编码方式修改为 UTF-8 这种类型的。(当让,修改工具你自选)
不改,不改你试试,如果不改的话,你的汉字所表示的区域将以乱码的形式展现在你面前!!!
好了,让我们看看 代码是怎么是实现的吧:
CCSVParse.h
#ifndef __C_CSV_PARSE__
#define __C_CSV_PARSE__
#include "cocos2d.h"
#include <vector>
using namespace std;
class CCSVParse
{
public:
//CCSVParse(void);
~CCSVParse(void);
CCSVParse(istream& fin=cin, string sep=","):
fieldsep(sep),
cols(0)
{
}
//用以存储数据
std::vector<std::vector<std::string>> data;
private:
string fieldsep;
int cols;
void StringSplit(const string& str, vector<string>& tokens, const char& delimiters);
void split(vector<string>& field, string line);
int advplain(const string& line, string& fld, int);
int advquoted(const string& line, string& fld, int);
public:
bool openFile(const char* fileName);
const char* getData(unsigned int rows, unsigned int cols);
int findColsData(int cols, const char* value);
inline int getCols(){return cols;}
inline int getRows(){return data.size();};
};
#endif //__C_CSV_PARSE__
CCSVParse.cpp
#include "CSVParse.h"
using namespace cocos2d;
// CCSVParse::CCSVParse(void)
// {
// }
CCSVParse::~CCSVParse(void)
{
for (unsigned int i=0; i<data.size(); i++)
{
data[i].clear();
}
data.clear();
}
// 查找 str 中的 delimiters ,然后在 delimiters 处分离 并将分离出来的字符串 放到 tokens 容器中
void CCSVParse::StringSplit( const string& str, vector<string>& tokens, const char& delimiters )
{
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
string::size_type pos = str.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos)
{
tokens.push_back(str.substr(lastPos, pos-lastPos));
lastPos = str.find_first_not_of(delimiters, pos);
pos = str.find_first_of(delimiters, lastPos);
}
}
void CCSVParse::split( vector<string>& field, string line )
{
string fld;
unsigned int i,j=0;
if( line.length() == 0 )
return;
i=0;
do
{
if(j<line.length() && line[i]=='"')
j = advquoted(line, fld, ++i);
else
j = advplain(line, fld, i);
field.push_back(fld);
i = j+1;
} while (j<line.length());
}
int CCSVParse::advplain( const string& s, string& fld, int i)
{
unsigned int j;
j = s.find_first_of(fieldsep, i);
if(j>s.length())
j=s.length();
fld = string(s,i,j-i);
return j;
}
int CCSVParse::advquoted( const string& s, string& fld, int i)
{
unsigned int j;
fld = "";
for (j=i; j<s.length(); ++j)
{
if(s[j]=='"' && s[++j]!='"')
{
unsigned int k = s.find_first_of(fieldsep, j);
if(k>s.length())
k = s.length();
for(k-=j; k-->0;)
fld += s[j++];
break;
}
fld += s[j];
}
return j;
}
//解析 CVS 文件
bool CCSVParse::openFile( const char* fileName )
{
string pathKey = CCFileUtils::sharedFileUtils()->fullPathForFilename(fileName);
unsigned char* pBuffer = nullptr;
unsigned long bufferSize = 0;
pBuffer = CCFileUtils::sharedFileUtils()->getFileData(pathKey.c_str(), "r", &bufferSize);
//一个字符占 1 位,一个汉字占 3 位,每行还有一个换行符 所以是 ( bufferSize = (5*3+24+1)*7 = 280 )
string s = (char*)pBuffer;
string str = s.substr(0,bufferSize);
vector<string> line;
StringSplit(str, line, '\n'); // 分离出 行 信息
for(unsigned int i=0; i<line.size(); ++i)
{
vector<string> field;
split(field, line[i]); // 分离出 每一行的 列 信息
data.push_back(field);
cols = max(cols, (int)field.size());
}
return true;
}
//获取指定行列的数据
const char* CCSVParse::getData(unsigned int rows, unsigned int cols )
{
if (rows<0 || rows>=data.size() || cols<0 || cols>=data[rows].size())
{
return "";
}
return data[rows][cols].c_str();
}
//获取指定数据的列下标
int CCSVParse::findColsData( int cols, const char* value )
{
for (unsigned int i=0; i<data.size(); ++i)
{
if(strcmp(getData(i,cols),value)==0)
return i;
}
return -1;
}
使用:
CCSVParse* csvFile = new CCSVParse();
csvFile->openFile("Book1.csv");
CCLog("csvFile->getRows() = %d, csvFile->getCols() = %d", csvFile->getRows(), csvFile->getCols() );
for (int i=0; i<csvFile->getRows(); ++i)
{
string strLine = "";
for(int j=0; j<csvFile->getCols(); ++j)
{
strLine += csvFile->getData(i,j);
strLine += ",";
}
CCLabelTTF* pLab = CCLabelTTF::create(strLine.c_str(),"Arial",20);
pLab->setPosition(ccp(visibleSize.width/2,visibleSize.height-90-i*30));
this->addChild(pLab,2);
}