在应用开发中,我们经常会把一些字符串,或一些结构体保存到文件中,保存到文件的方法一般都是先打开文件,然后将内容写入,最后再将文件关闭,这是不可避免的,相比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,从而也再不需要每次都打开关闭了,确实方便了不少。
本站部分资源收集于网络,纯个人收藏,无商业用途,如有侵权请及时告知!