前言
今天在用c++读取语言翻译表格CSV文件的时候,发现表格中的单元格内存在逗号和换行,于是搜了一下CSV格式的文件这两个字符的对应表示方法,发现都是一些其他语言的表示方法,未果。因为我之前做C#的,于是信心满满准备自己写个脚本来替换这CSV文件中逗号和换行符等一些乱七八糟的符号。但当我写起的时候发现C++各种方法和类都没有(连字符串替换字符串的方法都没有,C#中直接有string.replace,虽然c++也有该方法,但效果差强人意,根本不是想要的效果),都需要自己写,于是我又被这该死的c++狠狠折磨一顿。废话不多说,直接上代码。
代码
部分代码片段我贴在下面
#include "LanguageManager.h"
#include <string>
#include <fstream>
#include <iostream>
#include "uiData.h"
struct MyTranslation
{
//string tid;
string en; // 英语
string de; // 德语
string pt; // 葡萄牙
string es; //西班牙
string ja; //日语
};
map<string, MyTranslation> LanguageText; //记录表格中的语言配置
void LanguageManager::GetLanguageConfig()
{
ParseCSVFile("PuzzleLanguage.csv");
}
void LanguageManager::ParseCSVFile(string fileName)
{
//文件名错误
vector<string> fields = uiData::split(fileName, "."); //声明一个字符串向量
if (fields.size() < 2 || fields[fields.size() - 1] != "csv")
{
CCLOG("文件格式错误");
}
ifstream fin(fileName); //打开文件流操作
string line;
int lineCount = 0;
string buffer;
bool inside_quotes(false);
size_t last_quote(0);
while (getline(fin, buffer)) //整行读取,换行符“\n”区分,遇到文件尾标志eof终止读取
{
//---该处对单元格中的换行符处理---
last_quote = buffer.find_first_of('"');
while (last_quote != string::npos) //该行文末有解释
{
inside_quotes = !inside_quotes;
last_quote = buffer.find_first_of('"', last_quote + 1);
}
line.append(buffer);
if (inside_quotes)
{
line.append("\n");
continue;
}
//----换行符处理结尾处------
//下面是对读取到的内容解析
vector<string> files1 = uiData::split(line, ","); //声明一个字符串向量
string field;
if (files1.size() != 6)
{
continue;
}
MyTranslation trans;
string key = files1[0];
trans.en = files1[1];
trans.de = files1[2];
trans.pt = files1[3];
trans.es = files1[4];
trans.ja = files1[5];
LanguageText.insert(std::map<string, MyTranslation>::value_type(key, trans));
line.clear();
if (lineCount == 0)
{
lineCount++;
continue;
}
lineCount++;
}
}
//字符串分割 str:要分割的字符串 pattern:分割符
std::vector<std::string> uiData::split(std::string str, std::string pattern)
{
std::string::size_type pos;
std::vector<std::string> result;
str += pattern;//扩展字符串以方便操作
int size = str.size();
for (int i = 0; i < size; i++)
{
pos = str.find(pattern, i);
if (pos < size)
{
std::string s = str.substr(i, pos - i);
result.push_back(s);
i = pos + pattern.size() - 1;
}
}
return result;
}
其中对string::npos有疑问的可以看看这篇文章:C++中string::find()函数和string::npos函数的使用
参考:http://mybyteofcode.blogspot.com/2010/11/parse-csv-file-with-embedded-new-lines.html
over 欢迎指正
我以为这样就结束了
我以为这样就结束了,因为在PC设备上跑的完全没问题。结果今天打包到Android设备上跑,根本读不到数据,然而我从VS中导入AS中打包的,还没发调试到底哪出的问题。经过一步步打log终于定位到问题,就是上面的
ifstream fin(fileName); //打开文件流操作
这个在Android设备上根本就打不开文件CSV,而且我查找了很多相关的文档都没有涉及这方面的问题,顺便我还问了做Android的同事有没有读过CSV表格,他们表示并没有,所以也就没用过在Android设备上读取CSV文件的操作(如果你知道其中原因欢迎指出)。无奈只有重新写上面的方法,来读取配置文件。下面贴上代码
void LanguageManager::ParseCSVFile2()
{
char path[100];
sprintf(path, "PuzzleLanguage.csv");
char name[50];
sprintf(name, "PuzzleLanguage.csv");
string fullPath = CCFileUtils::sharedFileUtils()->fullPathFromRelativeFile(name, path);
unsigned char* pBuffer = NULL;
ssize_t bufferSize = 0;
pBuffer = CCFileUtils::sharedFileUtils()->getFileData(fullPath.c_str(), "r", &bufferSize);
string str;
str.append(reinterpret_cast<const char*>(pBuffer));
vector<string> itemDatas = uiData::split(str, "\r\n");
string line;
string buffer;
bool inside_quotes(false);
size_t last_quote(0);
for (int i = 0; i < itemDatas.size(); i++)
{
last_quote = itemDatas[i].find_first_of('"');
while (last_quote != string::npos)
{
inside_quotes = !inside_quotes;
last_quote = itemDatas[i].find_first_of('"', last_quote + 1);
}
line.append(itemDatas[i]);
if (inside_quotes)
{
line.append("\n");
continue;
}
vector<string> files1 = uiData::split(line, ","); //声明一个字符串向量
string field;
if (files1.size() != 6)
{
continue;
}
MyTranslation trans;
string key = files1[0];
trans.en = files1[1];
trans.de = files1[2];
trans.pt = files1[3];
trans.es = files1[4];
trans.ja = files1[5];
LanguageText.insert(std::map<string, MyTranslation>::value_type(key, trans));
line.clear();
}
}
该方法和之前的getline不同,该方法是直接把CSV文件当txt来读取,获取文件中的所有内容转换成字符串,然后再按照分隔符解析其中的内容。打包到Android设备没问题。
over 这下真的over了 欢迎指正~