C++简单文本读取(txt,csv,ini)

1 简单文本读取

对于简单文本,即文本在文件中没有特殊格式不需要进行解析,只需要简单的读取或写入文本中的每一行数据,可以通过C++中#include<fstream>提供的接口进行实现

1.1 C++方式的文件读写

C++提供了关于文件读写操作的接口#include<fstream>,其中ofstream类可以用于文件的写入,ifstream类可以用于文本的读取

对应c语言中"w"、“w+”等标识符。无论向文本中写入内容还是从文本中读取内容,可以通过在open函数中添加各种标识符作为参数,以不同的方式打开文件。

在进行文本操作时,以下方式是能够进行组合使用的,以“或”运算(“|”)的方式。

ios::in	    //为输入(读)而打开文件
ios::out	//为输出(写)而打开文件
ios::ate	//初始位置:文件尾
ios::app	//所有输出附加在文件末尾
ios::trunc	//如果文件已存在则先删除该文件
ios::binary	//二进制方式 

1.1.1 文本简单写入

#include<iostream>
#include<fstream>//定义了用于处理输入输出的类
#include<string>
using namespace std;

int main()
{
	string fileName = "./txtTest.txt";
	ofstream fout;
	
	//1.创建和打开文本文件
	//fout.open(fileName.c_str(), ios::out);//以文件写入的方式打开,若文件不存在则创建文件,若存在清空文件内容并重新写入
	fout.open(fileName.c_str(), ios::out | ios::app);//以文件写入并追加的方式打开,若文件不存在则创建文件
    //2.判断文件是否打开成功
    if (fout.is_open())
	{
		std::cout << "Creat and open file sucess!" << endl;
	}//if

	//3.向文件中写入文本
	for(int i=0;i<5;i++)
	{
		fout<<i<<" Hello word!"<<endl;
	}
	cout<<"Write file sucess!"<<endl;
    //4.关闭打开的文件
	fout.close();

    return 0;
}

1.1.2 文本简单读取

#include<iostream>
#include<fstream>//定义了用于处理文本输入与输出的类
#include<sstream>//定义了流的输入输出类
#include<string>

using namespace std;

int main()
{
	string fileName = "./txtTest.txt";
	ifstream fin;
	//打开文本文件
	fin.open(fileName.c_str(), ios::in);
	//判断文本文件是否成功打开
	if (!fin.is_open())
	{
		cout << "Open file failed!" << endl;
		exit(EXIT_FAILURE);//若打开失败则中断程序
	}
	else
		cout << "Open file sucess!" << endl;
	
	while (!fin.eof())//判断读取是否到达文件末尾
	{
		string str_txt;
		getline(fin,str_txt);//将一整行数据作为一个字符串读入
		if (!str_txt.empty())//判断该行数据是否读入成功
		{
			cout << str_txt << endl;

			//当文本的某一行既包含字符串又包含数字,或者包含多个类别的文本元素时,
			//如果想一次读取一行文本,并对该行的每一个元素分别处理可以使用stringstream类
			stringstream ss;
			ss << str_txt;
			int index;
			string message;
			ss >> index >> message;
			cout << index << "\t" << message << endl;
		}
	}
	fin.close();

	system("pause");
	return 0;
}

1.1.3 工程应用的一点思考

在工程应用中,有时文本文件可能用来存储程序运行过程中产生的一些Log文件,亦或是我们想要保存的一些数据,这种情况通过1.1.11.1.2中即可实现

但有时也会将文本作为参数文件,格式如下。这时可以结合string和map的一些操作,实现参数读取和查找某个固定参数的功能。

# students info

name=lsx
age=16
classes=9
grade=A
#include "stdafx.h"
#include<iostream>
#include<fstream>//定义了用于处理文本输入与输出的类
#include<sstream>//定义了流的输入输出类
#include<string>
#include<map>

using namespace std;
//参数读取类
class Params {
public:
	//构造函数
	Params()
	{
		//初始化文件名称
		string fileName = "param_config";
		ifstream fin;
		//打开文本文件
		fin.open(fileName.c_str(), ios::in);
		//判断文本文件是否成功打开
		if (!fin.is_open())
		{
			cout << "Open file failed!" << endl;
			exit(EXIT_FAILURE);//若打开失败则中断程序
		}
		else
			cout << "Open file sucess!" << endl;

		while (!fin.eof())//判断读取是否到达文件末尾
		{
			string str_txt;
			getline(fin, str_txt);//将一整行数据作为一个字符串读入
			if (!str_txt.empty())//判断该行数据是否为空
			{
				if (str_txt[0] == '#')//如果该行是以#开始,则是注释行,跳过
					continue;

				int pos = str_txt.find("=");//如果该行的数据格式不对则跳过
				if (pos == -1)
					continue;

				string key = str_txt.substr(0, pos);
				string value = str_txt.substr(pos + 1, str_txt.length());
				config_data[key] = value;
			}
			if (!fin.good())
				break;
		}
		fin.close();
	}

	//析构函数
	~Params()
	{
		map<string, string> map_empty;
		config_data.swap(map_empty);
		config_data.clear();
	}
    //查找key对应的value
	string getParamData(string key)
	{
		map<string, string>::iterator it = config_data.find(key);
		if (it == config_data.end())
		{
			cerr << "Parameter name " << key << " not found!" << endl;
			return string("NOT_FOUND");
		}
		return it->second;
	}

public:
	map<string,string> config_data;
};

int main()
{
	Params pa;
	string name = pa.getParamData("name");
	string age = pa.getParamData("age");
	string classes = pa.getParamData("classes");
	string grade = pa.getParamData("grade");

	cout << "student info:" << endl;
	cout << "\tname=" << name << endl;
	cout << "\tage=" << age << endl;
	cout << "\tclasses=" << classes << endl;
	cout << "\tgrade=" << grade << endl;

	system("pause");
	return 0;
}

2 csv文件读取

和上述简单文本读取操作相同,只不过在写入和读取文本时,CSV每一行中的每一个表格之间需要用逗号,隔开

如果不用逗号,隔开,那么输入的内容会被融合在一个表格中

#include "stdafx.h"
#include <iostream>
#include <string>  
#include <fstream>  
#include <sstream>  

using namespace std;


int main()
{
	string FileName = "./data.csv";
	//写文件
	ofstream fout;
	fout.open(FileName.c_str(),ios::out);
	if (!fout.is_open())
	{
		cout << "open or create file failed." << endl;
		exit(EXIT_FAILURE);
	}
	for (int i = 0; i < 5; i++)
		fout << 12 << "," << 13 << "," << 14 << "," << "Nan" << endl;
	fout.close();

	// 读文件  
	ifstream inFile("./data.csv", ios::in);
	string lineStr;
	while (getline(inFile, lineStr))
	{
		stringstream ss(lineStr);
		string c1, c2, c3, c4, c5;
		ss >> c1 >> c2 >> c3 >> c4 >> c5;
		cout << c1 << c2 << c3 << c4 << c5 << endl;
	}

	system("pause");
	return 0;
}

3 ini文件读取

找了半天没有找到一种比较好的方式解析ini配置文件,自己写一个简单的api吧

其实看ini配置文件的格式和txt类型的配置文件差不多,只不过他将所有的信息划分为若干个节Section

那感觉这样可以通过ofstreamifstream类提供的方法进行文件读写。

稍微不同的是,这里把每一个Section作为独立的一个map,然后把这个map放入一个更大的map中

但是这样做似乎有些粗糙,代码设计上不够优美;另外这里使用无序容器unordered_map替代map,因为map是一个支持自动排序的容器,每当插入一对新的键值对都会调用一次排序算法,这里我们换成unordered_map减少计算时间

这里只稍作演示,不考虑等号左右存在空格的情况
ini文件格式

# 个人信息
[info]
name=lsx
age=16
school=beijingUS
classes=9

# 体检信息
[health]
high=178
weight=65.3

# 成绩信息
[grade]
Chinese=120
English=132
Math=100

示例代码

#include "stdafx.h"
#include<iostream>
#include<fstream>//定义了用于处理文本输入与输出的类
#include<sstream>//定义了流的输入输出类
#include<string>
#include<map>
#include<unordered_map>//无序容器

using namespace std;
class Params {
public:
	//构造函数
	Params()
	{
		//初始化文件名称
		string fileName = "param.ini";
		ifstream fin;
		//打开文本文件
		fin.open(fileName.c_str(), ios::in);
		//判断文本文件是否成功打开
		if (!fin.is_open())
		{
			cout << "Open file failed!" << endl;
			exit(EXIT_FAILURE);//若打开失败则中断程序
		}
		else
			cout << "Open file sucess!" << endl;
		string section_name;
		while (!fin.eof())//判断读取是否到达文件末尾
		{
			string str_txt;
			getline(fin, str_txt);//将一整行数据作为一个字符串读入
			if (!str_txt.empty())//判断该行数据是否为空
			{
				if (str_txt[0] == '#')//如果该行是以#开始,则是注释行,跳过
					continue;

				//获取节的名称
				if (str_txt[0] == '[')
				{
					section_name = str_txt.substr(1,str_txt.length()-2);
					unordered_map<string, string> sub_map;
					data[section_name] = sub_map;
					continue;
				}
				else
				{
					int pos = str_txt.find("=");//如果该行的数据格式不对则跳过
					if (pos == -1)
						continue;

					string key = str_txt.substr(0, pos);
					string value = str_txt.substr(pos + 1, str_txt.length());
					data[section_name][key] = value;
				}
			}
			if (!fin.good())
				break;
		}
		fin.close();
	}

	//析构函数
	~Params()
	{
		unordered_map<string, unordered_map<string,string> > map_empty;
		data.swap(map_empty);
		data.clear();
	}

    //根据section和key的值,查找指定的value
	string getParamData(string section, string key)
	{
		//查找节section对应的map
		unordered_map<string, unordered_map<string, string> >::iterator it_total = data.find(section);
		if (it_total == data.end())
		{
			cerr << "Parameter section " << section << " not found!" << endl;
			return string("Section NOT_FOUND");
		}

		//查找具体的key对应的value
		unordered_map<string, string>::iterator it = data[section].find(key);
		if (it == data[section].end())
		{
			cerr << "Parameter name " << key << " not found!" << endl;
			return string("NOT_FOUND");
		}
		return it->second;
	}

public:
	//map<string, map<string,string> > data;
	unordered_map<string, unordered_map<string, string> > data;
};

int main()
{
	Params pa;
	string name = pa.getParamData("info","name");

	cout << "[info]name = " << name << endl;

	system("pause");
	return 0;
}
  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值