1. freopen & fopen #
C++语言提供了用于文件操作的标准函数。本节将介绍函数freopen和fopen,它们均包含在标准库cstdio中。文件操作的基本步骤如下:
(1)打开文件;
(2)进行读或者写操作;
(3)使用完文件后关闭文件。
1.1 fopen #
使用给定的模式 mode 打开 filename 所指向的文件。
1.1.1 fopen()的声明 #
FILE *fopen(const char *filename, const char *mode)
参数:
filename ——这是字符串,表示要打开的文件名称。
mode ——表示文件的访问模式,具体的模式如下表所示:
1.1.2 返回值 #
该函数返回一个 FILE 指针。否则返回 NULL,且设置全局变量 errno 来标识错误。
1.1.3 实例 #
#include <stdio.h> #include <stdlib.h> int main() { FILE * fp; fp = fopen ("file.txt", "w+"); fprintf(fp, "%s %s %s %d", "We", "are", "in", 2014); fclose(fp); return(0); }
编译并运行上面的程序,这将创建一个带有一下内容的文件 file.txt:
We are in 2014
使用下面的程序查看上面文件的内容:
#include <stdio.h> int main () { FILE *fp; int c; fp = fopen("file.txt","r"); while(1) { c = fgetc(fp); if( feof(fp) ) { break ; } printf("%c", c); } fclose(fp); return(0); }
1.2 freopen #
FILE *freopen(const char *filename, const char *mode, FILE *stream) 把一个新的文件名 filename 与给定的打开的流 stream 关联,同时关闭流中的旧文件。
1.2.1 freopen()的声明 #
FILE *freopen(const char *filename, const char *mode, FILE *stream)
参数:
filename ——这是字符串,表示要打开的文件名称。
mode ——表示文件的访问模式,与fopen()相同。
stream ——这是指向 FILE 对象的指针,该 FILE 对象标识了要被重新打开的流。
stdin:标准输入流,默认是键盘。
stdout:标准输入流,默认是键盘。
stderr:标准错误流,默认是屏幕。
1.2.2 返回值 #
如果文件成功打开,则函数返回一个指针,指向用于标识流的对象。否则,返回空指针。
1.2.3 实例 #
#include <stdio.h> int main () { FILE *fp; printf("该文本重定向到 stdout\n"); fp = freopen("file.txt", "w+", stdout); printf("该文本重定向到 file.txt\n"); fclose(fp); return(0); }
运行上面的程序,这将发送下列行到标准输出 STDOUT,因为起初我们并没有打开标准输出:
该文本重定向到 stdout
在调用 freopen() 之后,它会关联标准输出 STDOUT 到文件 file.txt,无论我们在标准输出 STDOUT 中写了什么都会被写入 file.txt,所以文件 file.txt 将有以下内容:
该文本重定向到 file.txt
使用下面的程序查看上面文件的内容:
#include <stdio.h> int main () { FILE *fp; int c; fp = fopen("file.txt","r"); while(1) { c = fgetc(fp); if( feof(fp) ) { break ; } printf("%c", c); } fclose(fp); return(0); }
1.3 复制、删除文件 #
1.3.1 复制文件 #
CopyFile函数定义在Windows.h中,使用时要include之;
CopyFile()使用如下:
#include <Windows.h> int main() { CopyFile("C:\\a.txt","C:\\b.txt",FALSE); }
便可将a.txt文件复制到b.txt文件,第三个参数表示: 如果目标已经存在,不拷贝(True)并返回False,覆盖目标(false)。
1.3.2 删除文件 #
要使用C++ 删除文件,需要使用int remove(const char * filename);方法,filename为要删除的文件名,可以为一目录。如果参数filename 为一文件,则调用unlink()处理;若参数filename 为一目录,则调用rmdir()来处理。删除成功则返回0,失败则返回-1,错误原因存于errno。C++中头文件是#include <cstdio>。
#include <iostream> #include <cstdio> #include <string.h> using namespace std; int main() { char *savePath = "/home/cjavapy/hello.txt"; if(remove(savePath)==0) { cout << "删除成功" << endl; } else { cout << "删除失败" << endl; } //输出错误信息 cout << strerror(errno); return 0; }
错误代码:
1)EROFS 欲写入的文件为只读文件。
2)EFAULT 参数filename 指针超出可存取内存空间。
3)ENAMETOOLONG 参数filename 太长。
4)ENOMEM 核心内存不足。
5)ELOOP 参数filename 有过多符号连接问题。
6)EIO I/O存取错误。
1.3.3 移动文件 #
MoveFile(A, B);表示将文件A移动到B
#include <fstream> #include <windows.h> int main() { char *fn = "test.txt"; std::ofstream out(fn); if (!out.is_open()) return 0; out.close(); WCHAR buf[256]; memset(buf, 0, sizeof(buf)); MultiByteToWideChar(CP_ACP, 0, fn, strlen(fn) + 1, buf, sizeof(buf) / sizeof(buf[0])); MoveFile(buf, L"../file/output.txt");//FALSE:将前者移动到后者中(后者路径若不错在,return 0) system("pause"); return 1; }
由函数原型可以看出,这两个函数的前两个输入参数都为LRCWSTR类型,如果我们定义的是char*,记得转换成LRCWSTR,否则会报错;
另外,这两个函数都返回一个bool型变量,表示执行成功与否,当目标位置路径不存在时,会return 0。
2. 文件输入输出流 #
之前使用的 iostream 标准库提供了 cin 和 cout 方法,分别用于从标准输入读取流和向标准输出写入流。
本节将介绍如何从文件读取流和向文件写入流。
2.1 三种数据类型 #
与iostream 标准库类似,C++ 中另一个标准库 fstream,它定义了三个新的数据类型:
要在 C++ 中进行文件处理,必须在 C++ 源代码文件中包含头文件 < iostream >和 < fstream >。
2.2 打开文件 #
在从文件读取信息或者向文件写入信息之前,必须先打开文件。ofstream 和 fstream 对象都可以用来打开文件进行写操作,如果只需要打开文件进行读操作,则使用 ifstream 对象。
下面是 open() 函数的标准语法,open() 函数是 fstream、ifstream 和 ofstream 对象的一个成员。
void open(const char *filename, ios::openmode mode);
在这里,open() 成员函数的第一参数指定要打开的文件的名称和位置,第二个参数定义文件被打开的模式。
可以把以上两种或两种以上的模式结合使用。例如,如果想要以写入模式打开文件,并希望截断文件,以防文件已存在,那么可以使用下面的语法:
ofstream outfile; outfile.open("file.dat", ios::out | ios::trunc );
类似地,如果想要打开一个文件用于读写,可以使用下面的语法:
ifstream afile; afile.open("file.dat", ios::out | ios::in );
2.3 关闭文件 #
当 C++ 程序终止时,它会自动关闭刷新所有流,释放所有分配的内存,并关闭所有打开的文件。但程序员应该养成一个好习惯,在程序终止前关闭所有打开的文件。
下面是 close() 函数的标准语法,close() 函数是 fstream、ifstream 和 ofstream 对象的一个成员。
void close();
2.4 读写文件 #
在 C++ 编程中,使用流插入运算符( << )向文件写入信息,就像使用该运算符输出信息到屏幕上一样。唯一不同的是,在这里使用的是 ofstream 或 fstream 对象,而不是 cout 对象。
在 C++ 编程中,我们使用流提取运算符( >> )从文件读取信息,就像使用该运算符从键盘输入信息一样。唯一不同的是,在这里您使用的是 ifstream 或 fstream 对象,而不是 cin 对象。
实例:
下面的 C++ 程序以读写模式打开一个文件。在向文件 afile.dat 写入用户输入的信息之后,程序从文件读取信息,并将其输出到屏幕上:
#include <fstream> #include <iostream> using namespace std; int main () { char data[100]; // 以写模式打开文件 ofstream outfile; outfile.open("afile.dat"); cout << "Writing to the file" << endl; cout << "Enter your name: "; cin.getline(data, 100); // 向文件写入用户输入的数据 outfile << data << endl; cout << "Enter your age: "; cin >> data; cin.ignore(); // 再次向文件写入用户输入的数据 outfile << data << endl; // 关闭打开的文件 outfile.close(); // 以读模式打开文件 ifstream infile; infile.open("afile.dat"); cout << "Reading from the file" << endl; infile >> data; // 在屏幕上写入数据 cout << data << endl; // 再次从文件读取数据,并显示它 infile >>; data; cout << data << endl; // 关闭打开的文件 infile.close(); return 0; }
当上面的代码被编译和执行时,它会产生下列输入和输出:
Writing to the file Enter your name: Zara Enter your age: 9 Reading from the file Zara 9
2.5 文本文件与二进制文件 #
2.5.1 文本文件 #
文本文件(text file,textfile,flatfile)一般指只有字符原生编码构成的二进制计算机文件,与富文本相比,其不包含字样样式的控制元素,能够被最简单的文本编辑器直接读取。
格式
ASCII、MIME、.txt、Windows的.txt文件
展示
用文本编辑器打开一个文本文件后,用户可以看到可读的纯文本内容。控制字符有时被编辑器当做文字指令,有时被当做像纯文本那样可编辑的转义字符。尽管文本文件里面有纯文本信息,但是通过特殊方法,文件内的控制字符(尤其是文件结束字符)可以让纯文本不可见。
2.5.2 二进制文件 #
二进制文件(英语:binary file)一般指包含ASCII及扩展ASCII字符中编写的数据或程序指令(program instructions)的文件。广义的二进制文件即为文件,由文件在外部存储设备的存放方式为二进制而得名。狭义的二进制文件即指除文本文件以外的文件。
二者区别
实在编程的概念里,只要是使用文本编辑器打开可以展现出人类可读的信息的文件,都可以算作宽泛的文本文件,如txt,html,css,java,xml等等,这些文件的编码都符合某种文字编码规范,如上文提到的ASCII、Unicode、还有以前中文中经常使用的GB2312;反之,如果文件的编码不符合任意一种文字编码规范,使用文本编辑器打开只能看到乱码,就可以认为它属于二进制文件。要想打开二进制文件,就必须要知道该文件所对应的编码规范,有些二进制文件使用通用的规范进行编码,比如常见的图片格式JPEG,音频格式MPEG-3,视频格式MPEG-4,而有些二进制文件的编码格式只有程序的开发者自己清楚,这样的文件对于普通的用户来说就几乎是保密的。