12.1const char*和char *const
const char*:不能修改其指向的内存中的内容,但可以修改其所指向的内存地址。
char *const:能修改其指向的内存中的内容,但不可以修改其所指向的内存地址。
12.2C语言对文件操作的支持
新建一个单文档类型的MFC程序,取名为File。
然后添加一个子菜单,名称为:文件操作。然后为其添加两个菜单项,并分别添加视类的命令响应函数:
ID:IDM_FILE_WRITE 菜单名称:写入文件 响应函数:OnFileWrite
ID:IDM_FILE_READ 菜单名称:读取文件 响应函数:OnFileRead
12.2.1文件的打开
首先利用fopen函数返回一个指向FILE结构体的指针:
FILE *fopen( const char *filename, const char *mode );
第一个参数表明将要打开的文件;第二个参数是文件打开的模式。
12.2.2文件的写入
向文件中写入可以用fwrite函数:
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
第一个参数指向将要写入的数据;第二个参数以字节为单位的项的大小;第三个参数写入项的最大数目;第四个参数指向FILE类型的指针。
接下来在视类OnFileWrite函数中实现文件的写入操作:
void CFileView::OnFileWrite()
{
// TODO: Add your command handler code here
FILE *pFile=fopen("1.txt","w");
fwrite("vc++",1,strlen("vc++"),pFile);
}
运行后,单击写入文件菜单项,打开File当前目录,发现新添加了一个该文件。但是打开此文件却发现没有任何内容。关闭运行的程序,再一次打开该文件,就可以看到文件中有内容了,如图。这是因为C语言对文件的操作使用了缓冲文件系统。
12.2.3文件的关闭
使用fclose函数关闭文件,表示对文件的写入操作已经完成,系统这是会把缓冲区中的内容写入磁盘文件中。
void CFileView::OnFileWrite()
{
// TODO: Add your command handler code here
FILE *pFile=fopen("1.txt","w");
fwrite("vc++",1,strlen("vc++"),pFile);
fclose(pFile);
}
运行发现,单击写入文件菜单项后,新增加的文件中就已经出现了内容了。
12.2.4fflush函数
如果希望对每次进行文件操作之后,并不关闭文件,但仍能将缓冲区中的数据立即写入磁盘文件中,这是可以调用fflush函数。
12.2.5文件指针定位
当调用文件写入函数向文件写入数据后,还可以再次写入其他数据。在fwrite(“vc++”,1,strlen(“vc++”),pFile);代码后面添加:
fwrite(“深入详解”,1,strlen(“深入详解”),pFile);
运行后,结果如图。
文件指针始终指向文件下一个将要写入的位置,所以当第二次调用fwrite函数之后,写入的内容接在第一次写入后面。
如果希望写入数据之后,在文件的开始位置继续写入,那可以利用C语言中fseek函数来实现:
int fseek( FILE *stream, long offset, int origin );
第一个参数指向FILE结构体;第二个参数为设定偏移量;第三个参数指定文件指针起始位置。
第三个参数:SEEK_CUR表示从文件当前位置开始;SEEK_END表示从文件结尾开始;SEEK_SET表示从文件开始处开始。
void CFileView::OnFileWrite()
{
// TODO: Add your command handler code here
FILE *pFile=fopen("1.txt","w");
fwrite("vc++",1,strlen("vc++"),pFile);
fseek(pFile,0,SEEK_SET);
fwrite("深入详解",1,strlen("深入详解"),pFile);
fclose(pFile);
}
运行结果如图。
12.2.6文件的读取
对于文件的读取,首先得打开文件,即调用fopen函数得到指向FILE类型的指针,然后如果要读取文件的内容,应该调用fread函数。
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
该函数与fwrite函数参数含义基本一致,只不过第一个参数是存放数据缓冲区的指针。
void CFileView::OnFileRead()
{
// TODO: Add your command handler code here
FILE *pFile=fopen("1.txt","r");
char ch[100];
fread(ch,1,100,pFile);
fclose(pFile);
MessageBox(ch);
}
运行结果如图。
可是发现在深入详解之后出现了一串乱码,原因就是应该在读取到的数据之后添加’\0’字符。
第一种方法就是在写入字符串的后面人为地加上一个’\0’。
void CFileView::OnFileWrite()
{
// TODO: Add your command handler code here
FILE *pFile=fopen("1.txt","w");
char buf[5]="vc++";
buf[4]='\0';
fwrite(buf,1,5,pFile);
fclose(pFile);
}
读取结果如图。但是这种方式的缺点是多写了一个字节。
第二种方法就是在定义字符数组之后,利用C语言memset函数将字符数组中所有的数据都设置为0:
void CFileView::OnFileRead()
{
// TODO: Add your command handler code here
FILE *pFile=fopen("1.txt","r");
char ch[100];
memset(ch,0,100);
fread(ch,1,100,pFile);
fclose(pFile);
MessageBox(ch);
}
这样当读取完字符串后就碰到’\0’,就会自动停止读取。
第三种方法就是利用ftell和rewind函数:ftell函数将文件的指针移动到文件的结尾处,也就是文件的长度;rewind函数将文件的指针重新放置到文件的开始处。
void CFileView::OnFileRead()
{
// TODO: Add your command handler code here
FILE *pFile=fopen("1.txt","r");
char *pBuf;
fseek(pFile,0,SEEK_END);
int len=ftell(pFile);
pBuf=new char[len+1];
rewind(pFile);
fread(pBuf,1,100,pFile);
pBuf[len]=0;
fclose(pFile);
MessageBox(pBuf);
}
12.2.7二进制文件和文本文件
文件分为二进制文件和文本文件,但实际上都是以二进制方式存储的。对于文本文件来说,他是一种特殊形式的文件,它所存放的每一个字节都可以转换为一个可读的字符,就像打开记事本看到a、b一样。如果以二进制方式保存文件,打开记事本就会看到其他字符。
在写入和读取文件时要保持一致,如果采用文本方式写入,就应该采用文本方式读取;如果采用二进制方式写入,就要采用二进制方式读取。
不管是文本文件还是二进制文件,统一采用二进制方式写入和读取是不会出错的。
不管是文本文件还是二进制文件,都可以采用二进制方式或文本方式打开,然后进行读取和写入。