C++ 文件操作
- 文件
- 为什么要使用文件
- 文件类型
- 文本文件 - 文件以文本的ASCII码形式存储在计算机中
- 二进制文件 - 文件以文本的二进制形式存储在计算机中
- 操作类型
- ofstream:写操作
- ifstream: 读操作
- fstream : 读写操作
- 文本文件
- 写文件
- 引入头文件 \<fstream>
- 创建一个输出文件流对象 ofstream
- 打开文件,并指定文件路径和打开方式,可以使用 open() 成员函数。
- 文件路径可以指定文件的**相对路径或绝对路径**。
- 打开方式
- 写入数据
- 关闭文件。可以使用流的 close() 成员函数来关闭文件。
- 示例
- 注意
- 读文件
- 引入头文件 \<fstream>。
- 创建一个输入文件流对象 ifstream
- 打开文件,并判断文件是否成功打开。
- 读取数据(4种)
- 关闭文件。可以使用流的 close() 成员函数来关闭文件。
- 示例
- 二进制文件
- 写入文件
- 函数原型
- 函数参数
- 示例
- 读文件
- 函数原型
- 函数参数(同写入一致)
- 示例
- 输入输出
- 输出(output)
- 输入(input)
文件
为什么要使用文件
程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被没了
通过文件可以将数据持久化
文件类型
文本文件 - 文件以文本的ASCII码形式存储在计算机中
它们包含了可读的字符数据,可以使用文本编辑器等工具直接打开查看和编辑。文本文件通常用于存储普通文本信息,如代码文件、配置文件、日志文件等。常见的文本文件扩展名有
.txt、.cpp、.h、.html 等。
二进制文件 - 文件以文本的二进制形式存储在计算机中
其中的数据是以二进制编码表示的。与文本文件不同,二进制文件中的数据不一定是可读的字符数据,用户一般不能直接读懂它们。二进制文件用于存储各种非文本类型的数据,如图像、音频、视频、数据库文件等。常见的二进制文件扩展名有
.jpg、.mp3、.avi、.dat 等。
操作类型
C++中对文件操作需要包含头文件 fstream
#include <fstream>
ofstream:写操作
这个类用于写操作,即将数据写入文件。你可以使用该类的对象创建或打开一个文件,并将数据写入文件。例如,你可以使用<<运算符将数据写入文件。
ifstream: 读操作
这个类用于读操作,即从文件中读取数据。你可以使用该类的对象打开一个已存在的文件,并从文件中读取数据。例如,你可以使用>>运算符从文件中读取数据。
fstream : 读写操作
这个类用于读写操作,既可以读取文件,也可以将数据写入文件。你可以使用该类的对象打开一个文件,然后通过读取和写入操作对文件进行处理。
这些类都是通过包含 头文件来使用的,该头文件提供了与文件输入输出相关的函数和类。
文本文件
写文件
引入头文件 <fstream>
首先,需要包含头文件 <fstream>,以便使用文件操作相关的类和函数。
#include <fstream>
创建一个输出文件流对象 ofstream
给它取一个合适的名字,比如 ofs。
ofstream ofs;
写文件可以利用 ofstream ,或者fstream类
打开文件,并指定文件路径和打开方式,可以使用 open() 成员函数。
ofs.open("文件路径", 打开方式);
文件路径可以指定文件的相对路径或绝对路径。
打开方式
ios::out:打开文件用于写入操作,若文件不存在则创建新文件,若文件已存在则清空原有内容。
ios::app:打开文件用于写入操作,在文件末尾追加写入数据,如果文件不存在,则创建新文件。
ios::ate:打开文件用于写入操作,将写指针定位到文件末尾,保留原有内容。
ios::trunc:打开文件用于写入操作,若文件已存在则清空原有内容,若文件不存在则创建新文件(默认行为)。
注意: 文件打开方式可以配合使用,利用|操作符
例如:用二进制方式写文件 ios::binary | ios:: out**
写入数据
你可以使用 << 运算符将需要写入的数据插入到文件流对象中。
ofs << "写入的数据";
在这里,你可以写入任何你想要写入的数据,比如字符串、数字等。
关闭文件。可以使用流的 close() 成员函数来关闭文件。
ofs.close();
关闭文件是一个很重要的步骤,它会确保所有的数据都被完整地写入到文件中,并释放资源。
示例
#include <iostream>
#include <fstream>
int main() {
std::ofstream ofs;
ofs.open("example.txt", std::ios::out);
if (ofs.is_open()) {
ofs << "Hello, World!";
ofs.close();
std::cout << "文件写入成功!" << std::endl;
} else {
std::cout << "无法打开文件。" << std::endl;
}
return 0;
}
在上述示例中,我们首先创建了一个 ofstream 对象 ofs,然后调用 open() 函数打开了一个名为 “example.txt” 的文件,打开方式为输出模式。接下来,使用 << 运算符将字符串 “Hello, World!” 插入到 ofs
对象中,相当于将这个字符串写入到文件中。最后,调用 close() 函数关闭文件。
注意
- 文件操作必须包含头文件 fstream
- 写文件可以利用 ofstream ,或者fstream类
- 打开文件时候需要指定操作文件的路径,以及打开方式
- 利用<<可以向文件中写数据
- 操作完毕,要关闭文件
可以使用输出操作符(如<<
)将数据写入文件,也可以使用成员函数(如write()
)进行更底层的写入操作。在完成文件写入后,建议调用 close()
方法关闭文件流。
需要注意的是,如果文件已经存在并且以 "ios::out"
模式打开文件,那么会清空文件内容并将新的内容写入文件。如果想要在已有文件的末尾追加内容,可以使用 "ios::app"
模式来打开文件。
读文件
引入头文件 <fstream>。
#include <fstream>
创建一个输入文件流对象 ifstream
ifstream ifs;
打开文件,并判断文件是否成功打开。
可以使用 open() 成员函数来打开文件,并通过 is_open() 成员函数检查文件是否成功打开。
ifs.open("文件路径", 打开方式);
if (ifs.is_open()) {
// 文件成功打开
} else {
// 文件打开失败
}
文件路径和打开方式同写入操作的要求一致
注意,文件必须存在且可读才能成功打开。
读取数据(4种)
-
使用输入流对象 >> 运算符读取数据
-
使用 getline() 函数逐行读取字符串数据
这种方式可以一次读取文件中的一行内容,存储在一个字符串变量中。
- 使用 get() 函数逐个字符地读取数据
这种方式可以逐个字符地读取文件中的数据。
- 使用 read() 函数读取指定数量的字节数据
这种方式可以读取指定数量的字节
关闭文件。可以使用流的 close() 成员函数来关闭文件。
ofs.close();
关闭文件是一个很重要的步骤,它会释放资源并确保文件操作的完整性。
示例
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ifstream ifs;
ifs.open("example.txt", std::ios::in);
if (ifs.is_open()) {
// 逐行读取字符串数据
std::string line;
while (std::getline(ifs, line)) {
std::cout << line << std::endl;
}
// 读取整数数据
int num;
ifs >> num;
std::cout << "读取到的整数是:" << num << std::endl;
ifs.close();
std::cout << "文件读取成功!" << std::endl;
} else {
std::cout << "无法打开文件。" << std::endl;
}
return 0;
}
在上述示例中,我们首先创建了一个 ifstream 对象 ifs,然后调用 open() 函数打开了一个名为 “example.txt” 的文件,打开方式为输入模式。接下来,使用 getline() 函数逐行读取文件中的字符串数据,并输出到标准输出流。然后,使用 >>
运算符将文件中的整数读取到变量 num 中,并输出。最后,调用 close() 函数关闭文件。
二进制文件
以二进制的方式对文件进行读写操作
打开方式要指定为 ios::binary
写入文件
使用二进制方式写入文件时,可以使用流对象的成员函数 write() 进行操作。
函数原型
ostream& write(const char* buffer, int len);
函数参数
buffer 是一个指向内存中一段存储空间的字符指针。在写入文件时,将从这段内存空间中读取数据。
len 是要读写的字节数,即从 buffer 中读取的数据长度。
可以通过调用 write() 函数多次连续写入更多数据。
注意,该函数返回流对象的引用,可以方便地进行链式操作。
示例
#include <iostream>
#include <fstream>
int main() {
std::ofstream ofs;
ofs.open("example.bin", std::ios::binary);
if (ofs.is_open()) {
int num = 42;
ofs.write(reinterpret_cast<const char*>(&num), sizeof(num));
float pi = 3.14f;
ofs.write(reinterpret_cast<const char*>(&pi), sizeof(pi));
ofs.close();
std::cout << "二进制文件写入成功!" << std::endl;
} else {
std::cout << "无法打开文件。" << std::endl;
}
return 0;
}
在上述示例中,我们创建了一个 ofstream 对象 ofs,然后调用 open() 函数打开名为 "example.bin"的文件,并以二进制方式进行操作。接下来,使用 write() 函数以二进制形式连续写入一个整数和一个浮点数到文件中。注意,我们使用reinterpret_cast 进行类型转换,将指向这些数据的指针转换为 const char* 类型,以便与 write() 函数的参数类型匹配。最后,调用 close() 函数关闭文件。
读文件
使用二进制方式读取文件时,可以使用流对象的成员函数 read() 进行操作。
函数原型
istream& read(char* buffer, int len);
函数参数(同写入一致)
buffer 是一个指向内存中一段存储空间的字符指针。读取的数据将被写入到这段内存空间中。
len 是要读取的字节数,即从文件中读取的数据长度。
可以通过调用 read() 函数多次连续读取更多的数据。
注意,该函数返回流对象的引用,可以方便地进行链式操作。
示例
#include <iostream>
#include <fstream>
int main() {
std::ifstream ifs;
ifs.open("example.bin", std::ios::binary);
if (ifs.is_open()) {
int num;
ifs.read(reinterpret_cast<char*>(&num), sizeof(num));
std::cout << "读取到的整数是:" << num << std::endl;
float pi;
ifs.read(reinterpret_cast<char*>(&pi), sizeof(pi));
std::cout << "读取到的浮点数是:" << pi << std::endl;
ifs.close();
std::cout << "二进制文件读取成功!" << std::endl;
} else {
std::cout << "无法打开文件。" << std::endl;
}
return 0;
}
在上述示例中,我们创建了一个 ifstream 对象 ifs,然后调用 open() 函数打开名为 “example.bin” 的文件,并以二进制方式进行操作。接下来,使用 read() 函数连续读取一个整数和一个浮点数的数据,并将其存储到相应的变量中。注意,我们使用 reinterpret_cast 进行类型转换,将指向这些数据的指针转换为 char* 类型,以便与 read()函数的参数类型匹配。最后,将读取到的整数和浮点数输出到标准输出流。最后,调用 close() 函数关闭文件。
输入输出
输出(output)
于文件操作,写入被称为输出(output),因为数据是从程序流向文件的。在C++中,文件输出被视为将数据从程序输出到文件。
因此,在C++中,我们使用输出流(output stream)来表示用于向文件写入数据的对象。这些输出流类(如 ofstream
和 fstream
)提供了方便的接口和方法,使我们能够轻松地将数据写入文件。
输出流的特点是数据从程序输出到文件,而输入流(input stream)则是数据从文件输入到程序。这种命名方式是为了与输入相对应,以更好地描述数据的流动方向。
总结一下,写入操作使用输出流来表示,是因为数据是从程序输出到文件的过程,而不是从文件输入到程序。
输入(input)
对于文件操作,读取被称为输入(input),因为数据是从文件流向程序的。在C++中,文件读取被视为将数据从文件输入到程序。
因此,在C++中,我们使用输入流(input stream)来表示用于从文件读取数据的对象。这些输入流类(如 ifstream
和 fstream
)提供了方便的接口和方法,使我们能够轻松地从文件中读取数据。
输入流的特点是数据从文件输入到程序,而输出流(output stream)则是数据从程序输出到文件。这种命名方式是为了更好地描述数据的流动方向。
总结一下,读取操作使用输入流来表示,因为数据是从文件输入到程序的过程,而不是从程序输出到文件。