C++读写文件

1. 文件读

CRead.h

#include <cstdio>
#include <string>

class CRead
{
public:
	enum EMode { M_BINARY, M_TEXT };

public:
	CRead(const char* fileName, EMode mode);

	~CRead();

	// 从文件读取指定字节数的数据。
	// 返回:
	//     读取的字节数量。
	int Read(void* buffer, int bytesToRead);

	// 改变文件中的当前位置。
	// finalPos         - 最终位置。
	// relativeMovement - 如果为真,“最终位置”为从当前位置相对移动的量。
	//                    如果为假,“最终位置”为从文件开头绝对移动的量。
	bool Seek(int finalPos,
		bool relativeMovement = false);

	// 获取文件的尺寸(字节数)。
	int GetSize() const;

	// 文件是否成功打开(文件句柄是否为真)。
	bool IsOpen() const;

	// 获取文件中的当前位置。
	// 以字节为单位,从文件开头开始,第1个位置号为0。
	int GetPosition() const;

	// 获取文件名。
	const char* GetFileName() const;

private:
	void OpenFile(EMode mode);

	std::string m_fileName;
	::FILE* m_file;
	int m_fileSize;

private:
	CRead(const CRead&);
	CRead& operator =(const CRead&);
};

CRead.cpp

#include "CRead.h"

CRead::CRead(const char* fileName, EMode mode)
	: m_file(nullptr)
	, m_fileSize(0)
{
	m_fileName = fileName;
	OpenFile(mode);
}

CRead::~CRead()
{
	if (m_file)
	{
		::fclose(m_file);
		m_file = nullptr;
	}
}

int CRead::Read(void* buffer, int bytesToRead)
{
	if (!IsOpen())
		return 0;

	size_t elementSize = 1;
	size_t elementCount = ::fread(buffer, elementSize, bytesToRead, m_file);
	return static_cast<int>(elementCount * elementSize);
}

bool CRead::Seek(int finalPos, bool relativeMovement)
{
	if (!IsOpen())
		return false;

	return ::fseek(m_file, finalPos,
		relativeMovement ? SEEK_CUR : SEEK_SET) == 0;
}

int CRead::GetSize() const
{
	return m_fileSize;
}

bool CRead::IsOpen() const
{
	return m_file != nullptr;
}

int CRead::GetPosition() const
{
	// 返回当前文件指针的位置。
	// 这个位置是指当前文件指针相对于文件开头的位移量,单位为字节。
	return ::ftell(m_file);
}

void CRead::OpenFile(EMode mode)
{
	if (m_fileName.empty())
	{
		m_file = nullptr;
		return;
	}

	errno_t err = ::fopen_s(&m_file, m_fileName.c_str(), mode == M_BINARY ? "rb" : "rt");
	if (err == 0 && m_file != nullptr)
	{
		::fseek(m_file, 0, SEEK_END);
		m_fileSize = GetPosition();
		::fseek(m_file, 0, SEEK_SET);
	}
	else
	{
		m_file = nullptr;
	}
}

const char* CRead::GetFileName() const
{
	return m_fileName.c_str();
}

2. 文件写

CWrite.h

#include <cstdio>
#include <string>

class CWrite
{
public:
	enum EMode { M_BINARY, M_TEXT, M_BINARY_APPEND, M_TEXT_APPEND };

public:
	CWrite(const char* fileName, EMode mode);

	~CWrite();

	// 向文件写入指定字节数的数据。
	// 返回:
	//     写入的字节数量。
	int Write(const void* buffer, int bytesToWrite);
	// 向文件写入含有终止符的字串。
	// 返回:
	//     写入的字节数量。
	int Write(const char* text);

	// 改变文件中的当前位置。
	// finalPos         - 最终位置。
	// relativeMovement - 如果为真,“最终位置”为从当前位置相对移动的量。
	//                    如果为假,“最终位置”为从文件开头绝对移动的量。
	bool Seek(int finalPos,
		bool relativeMovement = false);

	// 获取文件的尺寸(字节数)。
	int GetSize() const;

	// 文件是否成功打开(文件句柄是否为真)。
	bool IsOpen() const;

	// 获取文件中的当前位置。
	// 以字节为单位,从文件开头开始,第1个位置号为0。
	int GetPosition() const;

	// 获取文件名。
	const char* GetFileName() const;

private:
	void OpenFile(EMode mode);

	std::string m_fileName;
	::FILE* m_file;
	int m_fileSize;

private:
	CWrite(const CWrite&);
	CWrite& operator =(const CWrite&);
};

CWrite.cpp

#include "CWrite.h"

CWrite::CWrite(const char* fileName, EMode mode)
	: m_file(nullptr)
	, m_fileSize(0)
{
	m_fileName = fileName;
	OpenFile(mode);
}

CWrite::~CWrite()
{
	if (m_file)
	{
		::fclose(m_file);
		m_file = nullptr;
	}
}

int CWrite::Write(const void* buffer, int bytesToWrite)
{
	if (!IsOpen())
		return 0;

	size_t elementSize = 1;
	size_t elementCount = ::fwrite(buffer, elementSize, bytesToWrite, m_file);
	int writedBytes = static_cast<int>(elementCount * elementSize);
	m_fileSize += writedBytes;
	return writedBytes;
}

int CWrite::Write(const char* text)
{
	if (!IsOpen())
		return 0;
	size_t bytesToWrite = ::strlen(text);
	if (bytesToWrite < 1)
		return 0;

	size_t elementSize = 1;
	size_t elementCount = ::fwrite(text, elementSize, bytesToWrite, m_file);
	int writedBytes = static_cast<int>(elementCount * elementSize);
	m_fileSize += writedBytes;
	return writedBytes;
}

bool CWrite::Seek(int finalPos, bool relativeMovement)
{
	if (!IsOpen())
		return false;

	return ::fseek(m_file, finalPos,
		relativeMovement ? SEEK_CUR : SEEK_SET) == 0;
}

bool CWrite::IsOpen() const
{
	return m_file != nullptr;
}

int CWrite::GetSize() const
{
	return m_fileSize;
}

int CWrite::GetPosition() const
{
	return ::ftell(m_file);
}

void CWrite::OpenFile(EMode mode)
{
	if (m_fileName.empty())
	{
		m_file = nullptr;
		return;
	}

	char m[4] = { '\0' , '\0', '\0', '\0' };
	switch (mode)
	{
	case M_BINARY:
		m[0] = 'w';
		m[1] = 'b';
		break;
	case M_TEXT:
		m[0] = 'w';
		m[1] = 't';
		break;
	case M_BINARY_APPEND:
		m[0] = 'a';
		m[1] = '+';
		m[2] = 'b';
		break;
	case M_TEXT_APPEND:
		m[0] = 'a';
		m[1] = '+';
		m[2] = 't';
		break;
	default:
		m[0] = 'w';
		m[1] = 'b';
		break;
	}
	errno_t err = ::fopen_s(&m_file, m_fileName.c_str(), m);
	if (err == 0 && m_file != nullptr)
	{
		::fseek(m_file, 0, SEEK_END);
		m_fileSize = ::ftell(m_file);
		::fseek(m_file, 0, SEEK_SET);
	}
	else
	{
		m_file = nullptr;
	}
}

const char* CWrite::GetFileName() const
{
	return m_fileName.c_str();
}