赞
踩
网上关于使用 C++ 读写文件的内容不是所期待的,所以来写一下。
无论是读文件还是写文件,首先需要打开文件,需要使用两个类
这两个类继承自 std::io_base 用于处理 io 流。
需要包含头文件
#include <fstream>
两种打开文件的方式,
ifs.open("file.extension", openMode);
ifstream ifs("file.extension", openMode);
指定文件路径有多种方式
- 绝对路径 (完整路径,从硬盘的根目录出发),大概为以下格式:
// Windows 下 "C:/Documents and Settings/User/Desktop/file.txt" // Linux 下 "/home/user/file.txt"
- 1
- 2
- 3
- 4
- 相对路径 (从可执行文件 / exe 文件开始的路径),如果文件位于可执行文件下子目录 subdirectory 下则为
"subdirectory/file.txt"
- 1
- 如文件位于可执行文件所在的目录,则需要直接指定文件名即可
打开模式也来自 ios_base 类,需要指定命名空间 ios_base::
或 ios::
,由于我们需要使用读取的模式所以为 ios::in
表示 input,输入。
打开后,需要确定是否打开,if (ifs)
。
操作结束后,需要关闭,使用成员函数 close,ifs.close()
。
代码示例
#include <iostream> #include <fstream> using namespace std; int main(int argc, char* argv[]) { // 以读取方式打开 ifstream ifs("test.txt", ios::in); if (ifs) // 确保文件是否打开成功 { // 语句 ifs.close(); // 关闭文件 } else // 否则 cerr << "Unable to open the file !" << endl; return 0; }
当我们使用 ifstream 打开文件时,打开模式 ios::in
为可选内容,此选项为默认选项。
使用 ofstream 以写入的方式打开文件,同样有两种方式,一种直接声明,一种使用函数 open ,与 ifstream 相同。
对于写入,文件的打开方式有很多。
文件打开方式 | 速记 | 说明 |
---|---|---|
ios::out | output (输出) | 指定文件的打开方式为写入,一般为必要参数,但在使用 ofstream 对象时,为默认参数 |
ios::app | append (添加) | 当打开文件用于写入时,会在已有数据之后写入,不覆盖原有内容。使用此种打开方式,每次写入都会置于文件末尾,即便之前更改了位置。 |
ios::trunc | truncate (截断) | 当打开文件时,如果文件存在内容则清空文件内容 |
ios::ate | at end (在结束处) | 以写入方式打开文件,并将文件指针置于末尾。与 ios::app 不同之处为,如果改变了指针位置,写入不一定会在文件末尾 |
对于这些写入文件的打开方式,如果文件不存在则会创建。
用于指定多个打开模式,使用操作符或 |
。英文发音为 pipe 。
代码示例:
#include <iostream> #include <fstream> using namespace std; int main(int argc, char* argv[]) { ofstream ofs("test.txt", ios::out | ios::trunc); // 声明流与打开方式 if (ofs) // 文件是否打开 { // 操作语句 ofs.close(); // 关闭文件 } else // 否则 cerr << "Error to open file !" << endl; return 0; }
使用 fstream 可以以读写一起的方式打开文件,工作原理与 ifstream 和 ofstream 相同。
原型为
fstream flux("file.extension", ios::in|ios::out | [ios::trunc|ios::ate]);
中括号表示,需要使用两者中之一的打开方式
- 这是唯一的办法用以读取和写入的方式打开文件
- 中括号在实际代码中是不需要写的
- ios::app 是不可以选择的打开方式,此种文件打开方式,只允许在写入时使用,而此处 fstream 用于读取和写入
使用此种打开方式,文件必须存在!ios::in|ios::out
必须指定,由于文件已经存在,打开时需要指定 ios::ate
用于保留原始内容,或指定 ios::trunc
用于清空内容。
ifsteam, ofstream, fstream 都支持多种字符串格式
// const char *
explicit basic_fstream(const char* _Filename, ios_base::openmode _Mode = ios_base::in | ios_base::out, int _Prot = (int) ios_base::_Openprot);
// const string &
explicit basic_fstream(const string& _Filename, ios_base::openmode _Mode = ios_base::in | ios_base::out, int _Prot = (int) ios_base::_Openprot);
// const wchar_t *
explicit basic_fstream(const wchar_t* _Filename, ios_base::openmode _Mode = ios_base::in | ios_base::out, int _Prot = (int) ios_base::_Openprot);
// const wstring &
explicit basic_fstream(const wstring& _Filename, ios_base::openmode _Mode = ios_base::in | ios_base::out, int _Prot = (int) ios_base::_Openprot);
//....
ios_base::_Openprot 为打开保护
#include <fstream> #include <string> using namespace std; int main(int argc, char* argv[]) { string my_file = "text.txt"; fstream fs(my_file.c_str(), ios::in); if (fs) // 如果打开文件成功 { // 操作语句 fs.close(); // 关闭文件 } else // 否则 cerr << "Error to open file !" << endl; return 0; }
对于文件的读取,有多种不同的方法,如下
getline 需要两个参数,使用 ifstream 或 fstream 创建的流,和 用于存储内容的“目标”,通常为一个字符串,需要包含头文件 <string>
示例:
#include <iostream> #include <string> #include <fstream> using namespace std; int main(int argc, char* argv[]) { ifstream ifs("test.txt", ios::in); // 以读取模式打开 if (ifs) { string context; getline(ifs, context); cout << context; // 显示行 ifs.close(); } else cerr << "Unable to open the file !" << endl; return 0; }
为了读取完整的文件,需要一行一行的读取,需要一个重复的循环,getline 会读取到文件结束
if (ifs)
{
string line;
while (getline(ifs, line))
{
cout << line << endl;
}
}
getline 有一个重载方法,第三个参数为结束字符,这个结束字符的默认值为换行符 \n
,因此,我们可以一行一行的读取内容。
getline 只有在使用 ifstream 和 fstream 时有效,在 ofstream 时不再可用。
get 函数用于读取一个字符,当然在使用循环的情况下,也可以读取完整的文件。
语法为
stream.get(character);
这个方法读取文件中的一个字符,然后将其存储在 char 类型的 character 变量中。
示例
#include <iostream> #include <fstream> using namespace std; int main(int argc, char* argv[]) { ifstream ifs("test.txt", ios::in); if (ifs) { char character; // 字符型变量用于存储读取的字符 ifs.get(character); cout << character; ifs.close(); } else cerr << "Unable to open the file !" << endl; return 0; }
为了读取完整的文件,循环与 getline 相同。
这个符号应该不陌生,应该见到过与 cin 一起使用的情况,对于文件的运行原理也一样。这个操作符从文件中读取内容,直到遇到分隔符如空格或者换行符等。
比如一个文件中有以下内容
12 345
test
SDZ
可见,文件中存在两个整数和两个字符串,若我们需要全部获取到,需要声明两个 int
和 两个 string
示例:
#include <iostream> #include <string> #include <fstream> using namespace std; int main(int argc, char* argv[]) { ifstream ifs("test.txt", ios::in); if (ifs) { int integer1, integer2; string string1, string2; ifs >> integer1 >> integer2 >> string1 >> string2; ifs.close(); } else cerr << "Unable to open the file !" << endl; return 0; }
写入文件也有多种方式
这个符号对于了解 C++ 的人来说不应算陌生,它被用于 cout ,对于文件功能与显示到标准输出基本一致。
此操作符允许向文件中写入字符,或字符串,或整数…
操作符的使用语法为
stream << element1 << element2 << ...;
如代码所示与 cout 的使用并无太多区别。代码示例:
#include <iostream> #include <string> #include <fstream> using namespace std; int main(int argc, char* argv[]) { ofstream ofs("test.txt", ios::out | ios::trunc); if (ofs) { string name = "Zhangsan"; int age = 23; ofs << "Birthday: " << 25 << '/' << 6 << '/' << 1998 << endl; ofs << "Hello, " << name << ", you are " << age << " years old."; ofs.close(); } else cerr << "Unable to open the file !" << endl; return 0; }
我们向文件中写入 一些字符串,字符,一些整数和换行符。不需要显式声明类型,在使用时不用刻意区分,文本文件中内容如下:
Birthday: 25/6/1998
Hello, Zhangsan, you are 23 years old
put 被较少使用,由于不像 << 一样,只接受一个字符
使用时,只需要替换上述写入部分的代码
if (ofs)
{
char chr = 'X';
ofs.put(chr);
// 等价于 ofs.put('X');
ofs.close();
}
与 C 语言相似,也存在文件读写指针的概念,用于处理文件中的写入位置。
为了知道我们当前在文件中所处的位置,需要知道打开的方式
如果使用 ifstream 打开,存在方法 tellg()
如果使用 ofstream 打开, 存在方法 tellp()
这两种方法,返回当前文件指针所在的位置,从文件开始的字节编号。
stream.tell[g | p];
为了移动文件读写指针的位置,同样依赖文件的打开方式
如果使用 ifstream 打开
存在方法 seekg
,这个方法包含两个参数,第一个为字节的编号,第二个为从哪里开始计算这个编号,第二个参数可以为以下数值
默认值为 ios::beg
如果使用 ofstream 打开
方法几乎为同样的名称 seekp
,它的工作方式与 seekg
一致
stream.seek[g | p](10, ios::beg);
stream.eof()
,为了得知文件读写指针是否到达了文件尾;stream.ignore(num, characterEnd)
,用于忽略 num 个字符,或忽略所有直到遇到指定的 characterEnd 字符;stream.clear()
,用于将所有的标志位状态置为初始状态;stream.fail()
,用于测试文件流的打开是否正常,可用于检测一个文件是否存在标志位
英语为 flag ,即一个位,可以有两种值,0 或 1,对于 fstream 来讲,存在四个标志位,
这个方法返回一个布尔值,它会检查标志位 eofbit 是否为 true,即是否到达文件尾,否则为 false
eofbit 变为 true 的情况,要么是没有更多数据可以读取,要么是因为不能继续写入。
这个方法需要两个参数,需要忽略的字符数量以及一个终止的字符。它将忽略掉第一个参数数量个字符,直到遇到第二个参数指定的字符。此种方法可以用作计算文件的行数。
但需要注意两点
如果不提前知道文件的行数,也可以使用一种简便的方法,需要包含:
#inlcude <limits>
using namespace std;
在第一个参数处可以设置
numeric_limits<int>::max()
这个方法返回一个 int
最大能存储达的数值。一般为 2147483647
使用举例
stream.ignore(numeric_limits<int>::max(), '\n');
此方法用于重新置位 fstream 的四个标志位。
在文件读写指针到达文件尾时,eofbit 变为 true,如果此时需要回到文件首,如果不重新置位,则 eofbit 会一直处于 true 的状态,这时就会出问题
fail 方法用于实现 faibit 和 badbit 的检测,如果结果为 false,则表示文件流被正确创建,且打开成功。也保证了文件的存在
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。