- C文件I/O
- 1.1 文件类型
- 1.2 文件的打开与关闭
- 1.2.1文件打开
- 1.2.2文件关闭
- 1.3 文件的读写
- 1.3.1 fputc和fgetc
- 1.3.2 fwrite和fread
- 1.3.3 注意点
- 1.4 程序案例
- 1.4.1 fputc和fgetc的读写
- 1.4.2 fgets函数读取文件
- 1.4.3 fwrite和fread的读写
> 文本文件
又称为ASCII文件,文件中每个字节存放一个ASCII码,代表一个字符。
> 二进制文件
把内存中数据按照其在内存中的存储形式原样输出到磁盘上存放。
FILE* pFile = fopen(filePath, mode);
第一个参数:文件路径
第二个参数:打开方式
常用打开方式列表:
| 打开方式 | 含义 |
|---|---|
| “r” | 只读,文件必须存在 |
| “w” | 只写,文件不存在时创建文件,文件存在时原数据清零 |
| “a” | 追加,向文件末尾增加数据 |
| “rb” | 二进制,只读 |
| “wb” | 二进制,只写 |
| “ab” | 二进制,追加 |
| “r+” | 读写,打开一个文本文件 |
| “w+” | 读写,创建一个文本文件 |
fclose(pFile); // pFile为要关闭的文件指针1.3 文件的读写 1.3.1 fputc和fgetc
char result = fputc(ch, pFile); // 写入一个字符 char result = fgetc(pFile); // 读取一个字符1.3.2 fwrite和fread
size_t fwrite(const void* pBuffer, size_t nSize, size_t nCount, FILE* pFile);
参数
- pBuffer:一个指针,被写入数据的地址
- nSize:写入的字节数
- nCount:进行写入nSize字节的数据项的个数
- pFile:文件指针
返回值
如果成功,该函数返回一个 size_t 对象,表示元素的总数,该对象是一个整型数据类型。如果该数字与 nmemb 参数不同,则会显示一个错误。
size_t fread(void* pBuffer, size_t nSize, size_t nCount, FILE* pFile);
参数
- pBuffer:一个指针,读取数据的地址
- nSize:读取的字节数
- nCount:进行读取nSize字节的数据项的个数
- pFile:文件指针
返回值
成功读取的元素总数会以 size_t 对象返回,size_t 对象是一个整型数据类型。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。
读写最好采用配套操作,写如果用了"b"标记,读也最好用"b"标记。
1.4 程序案例 1.4.1 fputc和fgetc的读写#pragma warning(disable : 4996) #includeusing namespace std; class FileIO { public: FileIO(const string& strPath, const string& strMode); ~FileIO(); public: bool Initialize(); bool WriteToFile(const string& strData); bool ReadFromFile(string& strData); void Release(); private: string m_strPath; string m_strMode; FILE* m_pFile; bool m_bInitOk; }; FileIO::FileIO(const string& strPath, const string& strMode) : m_strPath(strPath), m_strMode(strMode), m_pFile(nullptr), m_bInitOk(false) { // ... } FileIO::~FileIO() { Release(); } bool FileIO::Initialize() { m_pFile = fopen(m_strPath.c_str(), m_strMode.c_str()); if (nullptr == m_pFile) { m_bInitOk = false; cout << "Create Or Open File Failedn"; return false; } m_bInitOk = true; return true; } bool FileIO::WriteToFile(const string& strData) { if (!m_bInitOk) { cout << "m_bInit Is Falsen"; return false; } size_t nLength = strData.length(); for (size_t i = 0; i != nLength; ++i) { // 如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF,并设置错误标识符。 if (EOF == fputc(strData.at(i), m_pFile)) { cout << "Write File Failedn"; return false; } } return true; } bool FileIO::ReadFromFile(string& strData) { if (!m_bInitOk) { cout << "m_bInit Is Falsen"; return false; } strData.clear(); // feof(m_pFile):此函数用于判断文件是否结束 while (!feof(m_pFile)) { char result = fgetc(m_pFile); if (EOF != result) strData.append(string(1, result)); } return true; } void FileIO::Release() { if (nullptr != m_pFile) { fclose(m_pFile); m_pFile = nullptr; } }
备注:在读取文件字符时不要使用下面的方式判断是否到文件尾部,因为文件中假设存在一个值为-1的字符,那么将会误判文件已经到尾部。
char result;
while(EOF != result)
{
result = fgetc(m_pFile);
}
1.4.2 fgets函数读取文件
char* fgets(char* str, int nLength, FILE* pFile);
参数
- str:这是指向一个字符数组的指针,该数组存储了要读取的字符串。
- nLength:这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
- pFile:这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。
返回值
如果成功,该函数返回相同的 str 参数。如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。如果发生错误,返回一个空指针。
备注
fgets函数读取一行,在遇到rn时,r被舍弃,只保留n
| 字符简称 | 含义 | 字符 | ASCII值 |
|---|---|---|---|
| CR | Carriage Return 回车 | ‘r’ | ASCII为13 |
| LF | LineFeed 换行 | ‘n’ | ASCII码为10 |
Unix/Linux换行使用:LF(0x0A)
Dos/Windows使用的是:CRLF(0x0D0A)
void Test()
{
FILE* pFile = fopen("Config.txt", "r");
if (nullptr == pFile)
{
cout << "Open File Failedn";
return;
}
char szBuffer[1024];
while (!feof(pFile))
{
memset(szBuffer, ' ', sizeof(szBuffer));
char* pResult = fgets(szBuffer, sizeof(szBuffer) - 1, pFile); // 减1为了保证最后一个字符为' '
if (nullptr == pResult)
continue;
// 清除行尾的回车符合换行符 回车:0x0D 换行:0x0A
int nLength = strlen(szBuffer);
if (nLength <= 0)
continue;
while ('r' == szBuffer[nLength - 1] || 'n' == szBuffer[nLength - 1])
{
szBuffer[nLength - 1] = ' ';
nLength = strlen(szBuffer);
if (nLength <= 0)
break;
}
printf("Line Data : %sn", szBuffer);
}
fclose(pFile);
}
1.4.3 fwrite和fread的读写
采用二进制方式进行结构体数据的读写
void WriteStudentData()
{
Student arrStu[2];
strcpy(arrStu[0].m_szName, "zhangsanA");
arrStu[0].m_nAge = 21;
arrStu[0].m_dScore = 99.5;
strcpy(arrStu[1].m_szName, "zhangsanB");
arrStu[1].m_nAge = 22;
arrStu[1].m_dScore = 92.5;
FILE* pFile = fopen("struct_file.bin", "wb");
if (nullptr == pFile)
{
cout << "Create File Failedn";
return;
}
// 一般可以不要 nResult 结果
size_t nResult = fwrite(arrStu, sizeof(Student), 2, pFile);
fclose(pFile);
}
void ReadStudentData()
{
Student arrStu[2];
FILE* pFile = fopen("struct_file.bin", "rb");
if (nullptr == pFile)
{
cout << "Open File Failedn";
return;
}
size_t nResult = fread(arrStu, sizeof(Student), 2, pFile);
fclose(pFile);
}



