#include <iostream> //std::cout #include <fstream> //std::ofstream using namespace std; int main() { const char * url = "http://c.biancheng.net/cplus/"; //以文本模式打开out.txt ofstream destFile("out.txt", ios::out); if (!destFile) { cout << "文件打开失败" << endl; return 0; } //向out.txt文件中写入 url 字符串 destFile << url; //关闭打开的 out.txt 文件 destFile.close(); return 0; }
执行该程序,会生成一个 out.txt 文件,内部存有如下内容:
http://c.biancheng.net/cplus/
前面提到,在某些情况下(例如上面程序中),即便不显式调用 close() 方法,文件的读写操作也能成功执行。因为当文件流对象的生命周期结束时,会自行调用析构函数,此函数内部会先调用 close() 方法切断文件流对象与任何文件的关联,最后才销毁它。
那么,既然文件流对象自行销毁时会隐式调用 close() 方法,是不是就不用显式调用 close() 方法了呢?
当然不是。在实际进行文件操作的过程中,对于打开的文件,要及时调用 close() 方法将其关闭,否则很可能会导致读写文件失败。
举个例子(程序二):
#include <iostream> //std::cout #include <fstream> //std::ofstream using namespace std; int main() { const char * url = "http://c.biancheng.net/cplus/"; //以文本模式打开out.txt ofstream destFile("out.txt", ios::out); if (!destFile) { cout << "文件打开失败" << endl; return 0; } //向out.txt文件中写入 url 字符串 destFile << url; //程序抛出一个异常 throw "Exception"; //关闭打开的 out.txt 文件 destFile.close(); return 0; }
通过对比不难发现,此程序和程序一唯一的区别在于,第 17 行添加了抛出异常的语句。由于程序中没有对抛出的异常进行处理,因此当程序执行到此行时会崩溃。
更重要的是,第 17 行会导致文件写入操作失败。执行此程序,同样会生成 out.txt 文件,但 "http:c.biancheng.net/cplus/" 字符串并没有成功被写入。
也就是说,对于已经打开的文件,如果不及时关闭,一旦程序出现异常,则很可能会导致之前读写文件的所有操作失效。在程序二的基础上,如果将第 17 行代码和第 19 行代码互换,再次执行程序会发现,虽然程序执行仍会崩溃,但 "http:c.biancheng.net/cplus/" 字符串可以被成功写入到 out.txt 文件中。
C++ flush()刷新缓冲区
在很多实际场景中,即便已经对文件执行了写操作,但后续还可能会执行其他的写操作。对于这种情况,我们可能并不想频繁地打开/关闭文件,可以使用 flush() 方法及时刷新输出流缓冲区,也能起到防止写入文件失败的作用。
程序二之所以写入文件失败,是因为 << 写入运算符会先将 url 字符串写入到输出流缓冲区中,待缓冲区满或者关闭文件时,数据才会由缓冲区写入到文件中。但直到程序崩溃,close() 方法也没有得到执行,且 destFile 对象也没有正常销毁,所以 url 字符串一直存储在缓冲区中,没有写入到文件中。
比如,修改程序二的代码:
#include <iostream> //std::cout #include <fstream> //std::ofstream using namespace std; int main() { const char * url = "http://c.biancheng.net/cplus/"; //以文本模式打开out.txt ofstream destFile("out.txt", ios::out); if (!destFile) { cout << "文件打开失败" << endl; return 0; } //向out.txt文件中写入 url 字符串 destFile << url; //刷新输出流缓冲区 destFile.flush(); //程序抛出一个异常 throw "Exception"; //关闭打开的 out.txt 文件 destFile.close(); return 0; }
可以看到,在程序二的基础上,在第 17 行调用了 flush() 方法。再次执行程序,虽然仍执行崩溃,但 "http://c.baincheng.net/cplus/" 字符串成功写入到了 out.txt 文件中。
总之,C++ 中使用 open() 打开的文件,在读写操作执行完毕后,应及时调用 close() 方法关闭文件,或者对文件执行写操作后及时调用 flush() 方法刷新输出流缓冲区。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/23709.html