他小的有

C++一个文件操作类的封装

在应用开发中,我们经常会把一些字符串,或一些结构体保存到文件中,保存到文件的方法一般都是先打开文件,然后将内容写入,最后再将文件关闭,这是不可避免的,相比C#中的File.ReadAllText,WriteAllText,ReadAllBuffer,WriteAllBuffer实在是麻烦不少,既然经常有这样的需求,我们可以将它们写成一个函数,能比较方便的调用而且在以后的项目中复用,代码如下:

//ZFile.hpp

#pragma once
#include <string>
#include <vector>
#include <fstream>

/*!
 * 文件操作模版类
 * 
 */
template <class tchar>
class ZFileT
{
public:
	typedef std::basic_string<tchar, std::char_traits<tchar>, std::allocator<tchar> >
		this_string;

	typedef std::basic_istringstream<tchar, std::char_traits<tchar>, std::allocator<tchar> >
		this_istringstream;

public:
	/*!
	* 读取文件缓冲区数据
	*
	* \param path 文件路径
	* \param context 内容
	* \return 成功返回true,否则返回false。
	*/
	static bool Read(const this_string &path, std::vector<char> &context)
	{
		std::ifstream ifs;
		ifs.open(path, std::ios::binary);
		if (!ifs.is_open())
			return false;

		//获取文件大小
		auto pos = ifs.tellg();
		ifs.seekg(0, std::ios::end);
		auto size = ifs.tellg();
		ifs.seekg(pos);

		//读取全部
		context.resize((size_t)size);
		ifs.read(context.data(), size);
		ifs.close();
		return ifs.good();
	}

	/**
	* 将缓冲区的数据写入文件
	*
	* \param path 文件路径
	* \param buffer 缓冲区
	* \param size 字节数
	* \return 成功返回true,否则返回false
	* \note 如果文件已经存在,之前的内容都将被清除,如果内容不存在,则创建新的文件
	*/
	static bool Write(const this_string &path, const void *buffer, size_t size)
	{
		std::ofstream ofs;
		ofs.open(path, std::ios::binary);
		if (!ofs.is_open())
			return false;

		//写入缓冲区数据到文件
		ofs.write((const char *)buffer, size);
		ofs.close();
		return ofs.good();
	}

	/*!
	* 读取文件所有文本内容
	*
	* \param path 文件路径
	* \param text 字符串引用
	* \return 如果成功返回true,否则返回false。
	*/
	static bool ReadAllText(const this_string &path, std::string &text)
	{
		std::ifstream ifs(path);
		if (!ifs.is_open())
			return false;

		//读取文件
		std::istreambuf_iterator<char>beg(ifs), end;
		text.assign(beg, end);
		ifs.close();
		return ifs.good();
	}

	/*!
	* 写入所有文本
	*
	* \param path 文件路径
	* \param text 字符内容
	* \return 如果成功返回true,否则返回false。
	*/
	static bool WriteAllText(const this_string &path, const std::string &text)
	{
		std::ofstream ofs(path);
		if (!ofs.is_open())
			return false;

		//内容流入文件
		ofs << text;
		ofs.close();
		return ofs.good();
	}

	/*!
	* 读取所有行
	*
	* \param path 文件路径
	* \param lines 行容器
	* \return 如果成功返回true,否则返回false。
	*/
	static bool ReadAllLines(const this_string &path, std::vector<std::string> &lines)
	{
		std::ifstream ifs(path);
		if (!ifs.is_open())
			return false;

		//读取到并放到容器中
		std::string line;
		while (!ifs.eof() && !ifs.bad())
		{
			getline(ifs, line);
			lines.push_back(line);
		}
		ifs.close();
		return !ifs.bad();  //此处不能使用ifs.good(),ifs.eof()为true时此函数返回false
	}
};

typedef ZFileT<char>
ZFileA;
typedef ZFileT<wchar_t>
ZFileW;

#ifdef UNICODE
typedef ZFileW ZFile;
#else
typedef ZFileA ZFile;
#endif // UNICODE


测试用例

/***** File *****/
namespace ZFileTest
{
	//缓冲区写入文件
	TEST(ZFile, WriteAndRead)
	{
		const wchar_t *pszFilePath = L"temp.txt";
		std::vector<char> write;
		write.push_back('A');
		write.push_back('B');
		write.push_back('\r');
		write.push_back('\n');
		write.push_back('C');
		EXPECT_TRUE(ZFile::Write(pszFilePath, write.data(), write.size()));

		std::vector<char> read;
		EXPECT_TRUE(ZFile::Read(pszFilePath, read));
		EXPECT_EQ(write.size(), read.size());
		for (size_t i = 0; i < write.size(); ++i)
		{
			EXPECT_EQ(write[i], read[i]);
		}
	}

	//写读文件内容
	TEST(ZFile, WriteAllTextAndReadAllText)
	{
		const wchar_t *pszFilePath = L"temp.txt";
		std::string strWrite = "今天没有作业";
		std::string strRead;
		EXPECT_TRUE(ZFile::WriteAllText(pszFilePath, strWrite.c_str()));
		EXPECT_TRUE(ZFile::ReadAllText(pszFilePath, strRead));
		EXPECT_EQ(strWrite, strRead);
	}

	//读取文件所有行
	TEST(ZFile, ReadAllLines)
	{
		//不存在时
		{
			auto strFileNameNotExist = ZPath::GetCurrentPath() + (L"\\lines_not_exist.txt");
			std::vector<std::string> lines;
			EXPECT_FALSE(ZFile::ReadAllLines(strFileNameNotExist, lines));
		}

		auto strFileName = ZPath::GetCurrentPath() + (L"\\lines.txt");
		std::vector<std::string> lines;
		EXPECT_TRUE(ZFile::ReadAllLines(strFileName, lines));
		EXPECT_EQ(lines.size(), 3);
		EXPECT_EQ(lines[0], "line0");
		EXPECT_EQ(lines[1], "line1");
		EXPECT_EQ(lines[2], "line2");
	}
}

像这样子,任何地方需要读写文本文件所有内容时只需要ZFile::ReadAllText/ZFile::WriteAllText,从而也再不需要每次都打开关闭了,确实方便了不少

本站部分资源收集于网络,纯个人收藏,无商业用途,如有侵权请及时告知!

0
分享到:

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址