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,而有些二进制文件的编码格式只有程序的开发者自己清楚,这样的文件对于普通的用户来说就几乎是保密的。