【C++】C++读取CSV文件中换行符的处理

前言

今天在用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了 欢迎指正~

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值