C语言中文件常见操作的示例详解
目录
- 文件打开和关闭
- 文件写入
- 文件读取
- fseek函数
- ftell函数
- Demo示例
- 解决读取乱码
FILE为C语言提供的文件类型,它是一个结构体类型,用于存放文件的相关信息。文件打开成功时,对它作了内存分配和初始化。
每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。
一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。
文件打开和关闭
C语言的安全文件打开函数为_wfopen_s和_fopen_s。
errno_t _wfopen_s( FILE** pFile, const wchar_t *filename, const wchar_t *mode );
参数pFile
指向文件指针的指针,该文件指针将接收指向打开文件的指针。
参数filename
表示要打开的文件名
参数mode
表示访问方式,该参数可设置的值如下表。
模式 | 含义 |
---|---|
"r" | 打开以供阅读。如果文件不存在或找不到,则fopen_s调用将失败 |
"w" | 打开一个空文件进行写入。如果给定文件存在,则其内容将被销毁 |
"a" | 在新数据写入文件之前,在文件末尾打开以写入(追加),而不删除文件结束 (EOF) 标记。如果文件不存在,则创建该文件 |
"r+" | 可打开读取和写入。该文件必须存在 |
"w+" | 打开一个空文件进行读取和写入。如果该文件存在,则其内容将被销毁 |
"a+" | 打开以供阅读和追加。追加操作包括在将新数据写入文件之前删除 EOF 标记。写入完成后,不会还原 EOF 标记。如果文件不存在,则创建该文件 |
除了上述模式外,还可以包含以下字符,以指定换行符的转换模式:
模式修改器 | 翻译模式 |
---|---|
t | 以文本(翻译)模式打开。 |
b | 以二进制(未翻译)模式打开;禁止显示涉及回车符和换行符的转换。 |
返回值
如果成功,则为零;失败时的错误代码
使用Close函数文件关闭。
文件写入
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
参数buffer
表示存储读取数据的缓冲区
参数size
表示要写入数据的一个字符的大小(以字节为单位)
参数count
表示要写入数据的字符数
参数stream
表示指向文件结构体的指针
返回值
fwrite返回函数写入的完整项数,如果发生错误,该数可能小于count。
文件读取
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
参数buffer
表示存储读取数据的缓冲区
参数size
表示要读取数据的一个字符的大小(以字节为单位)
参数count
表示要读取数据的字符数
参数stream
表示指向文件结构体的指针
返回值
fread返回函数读取的完整项目数,如果发生错误,或者在达到COUNT 之前遇到文件末尾,则可能小于Count。
fseek函数
可以通过fseek函数设置文件指针的位置。通过该方法可以计算出文件的大小
int fseek( FILE *stream, long offset, int origin );
参数stream
表示指向文件结构体的指针
参数offset
表示指针的偏移量
参数origin
表示指针所处位置 ,其可以设置的如下的取值
取值 | 意义 |
---|---|
SEEK_CUR | 文件指针的当前位置 |
SEEK_END | 文件结束 |
SEEK_SET | 文件的开头 |
ftell函数
ftell函数可以获取文件指针的当前位置。通过fseek结合ftell两个函数可以计算出文件的大小
long ftell( FILE *stream );
Demo示例
写数据:
void CMyFileCFileView::OnFileWrite() { FILE* pFile = NULL; //打开文件 errno_t err = _wfopen_s(&pFile, _T("1.txt"), _T("w")); if (err != 0) { TRACE("Open File failed errorcode :%d", GetLastError()); return; } fwrite(L"Hello World", 2, wcslen(L"Hello World")+1, pFile); fclose(pFile); }
读数据:
void CMyFileCFileView::OnFileRead() { FILE* pFile = NULL; errno_t err = _wfopen_s(&pFile, _T("1.txt"), _T("r")); if (err != 0) { TRACE("Open File failed errorcode :%d", GetLastError()); return; } fseek(pFile, 0, SEEK_END);//文件指针定位,偏移到结尾 int len = ftell(pFile);//得到文件指针的当前位置 = 每个字符大小×字符长度 WCHAR* pBuf = new WCHAR[len]; fseek(pFile, 0, SEEK_SET);//文件指针回到文件起始位置 pBuf[len] = 0; fread(pBuf, 2, len, pFile); MessageBox(pBuf); fclose(pFile); }
解决读取乱码
使用C语言进行文件操作时如果稍微不注意很容易读出乱码。一般出现这种乱码有两种原因,一种时写入的数据没有写入结束符,另一种是读取数据时,读取数据的个数设置出错。
例如下面这种写入数据和读取数据的代码,运行出来就会出现乱码。
//写数据 fwrite(L"Hello World", 2, wcslen(L"Hello World"), pFile); //读数据 //pFile此时移动到了文件末尾 int len = ftell(pFile);//得到文件指针的当前位置 = 每个字符大小×字符长度 WCHAR* pBuf = new WCHAR[len]; fseek(pFile, 0, SEEK_SET);//文件指针回到文件起始位置 fread(pBuf, 2, len, pFile);
使用ftell获取的文件指针到的位置为 一个字符大小 ×字符长度。 虽然"Hello World"有11个字符,但是WCHAR类型,所以ftell返回的值为22。在之后使用fread读取数据时读到了len×2=44字节的内容,而写入的数据才22字节,因此会出现乱码。
解决方法:
方法一:给存储的数据结尾加上结束符'\0"
在写数据时:
fwrite(L"Hello World", 2, wcslen(L"Hello World")+1, pFile);
写入的实际长度+1,这样写入的数据后面会增加一个'\0'结束符。
fread在达到COUNT 之前遇到文件末尾也会停止。这样在缓冲缓冲数组就可以读到实际数据和一个结束符。打印时就能正常打印出。
//写数据 fwrite(L"Hello World", 2, wcslen(L"Hello World")+1, pFile); //读数据 //pFile此时移动到了文件末尾 int len = ftell(pFile);//得到文件指针的当前位置 = 每个字符大小×字符长度 WCHAR* pBuf = new WCHAR[len]; fseek(pFile, 0, SEEK_SET);//文件指针回到文件起始位置 fread(pBuf, 2, len, pFile);
方法二:限制读取的大小
因为len得到的是一个字符的大小×字符数,如果把len/sizeof(WCHAR),就可以获得实际的字符数。在读取数据时使用这个实际的长度作为读取数,之后将缓冲数组len的位置赋值为'\0'。就可以读取到实际数据
//写数据 fwrite(L"Hello World", 2, wcslen(L"Hello World"), pFile); //读数据 //pFile此时移动到了文件末尾 int len = ftell(pFile);//得到文件指针的当前位置 = 每个字符大小×字符长度 WCHAR* pBuf = new WCHAR[len]; fseek(pFile, 0, SEEK_SET);//文件指针回到文件起始位置 fread(pBuf, 2, len/2, pFile); pBuf[len/2] = 0;
到此这篇关于C语言中文件常见操作的示例详解的文章就介绍到这了,更多相关C语言文件操作内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!