C++读写文件
1.问题
C++如何快速方便的读写文件?
2.解决
参考:C/C++ 文件读写
2.1 使用freopen
•C中的文件读写-freopen
函数简介
freopen 是被包含于 C标准库头文件 stdio.h 中的一个函数,用于重定向输入输出流。
该函数可以在不改变代码原貌的情况下改变输入输出环境,但使用时应当保证流是可靠的。
函数声明
*FILE freopen(const char* _FileName, const char* _Mode, FILE* _Stream );
-
_FileName:需要重定向的文件名或文件路径
-
_Mode:代表文件访问权限的字符串
-
"r" 表示 只读访问
-
"w" 表示 只写访问
-
"a" 表示 追加写入
-
_Stream:需要被重定向的文件流
- stdin:表示输入重定向(从指定文件中读取数据到程序中)
- stdout:表示输出重定向(将程序中输出的数据输入到指定文件中)
-
返回值:如果成功,则返回指向该输出流的文件指针,否则返回为NULL
测试输出重定向(写文件)
新建一个项目,并命名为文件读写;
在该项目中创建一个 C中的文件读写.c 文件,并添加如下代码:
#include<stdio.h>
#define FILENAME "FILEC.txt"//文件名
void write()
{
freopen(FILENAME, "w", stdout);
printf("测试向FILEC.txt中写文件\\n");
}
int main()
{
write();
return 0;
}
运行该代码,你会发现,在项目文件读写的文件夹下多出一个 FILEC.txt 的文件,打开该文件,你会惊奇的发现,该文件的内容就是你在程序中通过 printf 输出的语句。
通过代码可以看出,freopen 函数只出现在了 write() 函数中,那么如果在主函数中输出 "Hello World",会输出到哪里呢?
让我们通过代码来测试一下。
void write()
{
freopen(FILENAME, "w", stdout);
printf("测试向FILEC.txt中写文件\\n");
}
int main()
{
printf("TEST1 : Hello World\\n");
write();
printf("TEST2 : Hello World\\n");
return 0;
}
运行该代码,你会发现,在控制台只输出了 "TEST1 : Hello World":
少的那一句呢?
莫非是输出到 FILEC.txt 中了,让我们一探究竟。
果然在这里,通过这个测试,就能发现,在语句 freopen(FILENAME, "w", stdout); 调用后,所有的输出语句都写到了 FILEC.txt 中。
C 语言中提供了文件读写的关闭语句 fclose(stdout) ,那可不可以通过该语句实现随开随关呢?
让我们尝试在 write() 中使用该语句。
void write()
{
freopen(FILENAME, "w", stdout);
printf("测试向FILEC.txt中写文件\\n");
fclose(stdout);
}
int main()
{
printf("TEST1 : Hello World\\n");
write();
printf("TEST2 : Hello World\\n");
return 0;
}
让我们来运行一下修改后的程序。
运行结果
在 VS2022 上,直接报错了:
而在 CodeBlocks 中测试,成功运行了:
但是, FILEC.txt 文件中却丢失了 printf("TEST2 : Hello World\n"); 语句的输出结果:
所以,通过测试可知,并不能通过 fclose(stdout); 语句实现随开随关 ,正确的写法应该是:
#include<stdio.h>
#define FILENAME "FILEC.txt"//文件名
void write()
{
freopen(FILENAME, "w", stdout);
printf("测试向FILEC.txt中写文件\\n");
}
int main()
{
printf("TEST1 : Hello World\\n");
write();
printf("TEST2 : Hello World\\n");
fclose(stdout);//放置到程序结尾处
return 0;
}
测试输入重定向(读文件)
在程序所在目录下新建一个 Input.txt 文件,并输入如下信息:
运行如下代码:
#include<stdio.h>
#define FILENAME "Input.txt"
int main()
{
freopen(FILENAME,"r",stdin);//读文件
char s\[100\];
while (scanf("%s", s) != EOF)
puts(s);
return 0;
}
运行该程序,你会发现,并不需要输入任何数据:
控制台输出的内容刚好是 Input.txt 中的内容。
- scanf("%s", s) != EOF 表示的是读取到文件结尾
- FILENAME 也可以换成 Input.txt 的具体路径
E:\\Documents\\Visual Studio for C++\\文件读写\\文件读写\\Input.txt
- 其中,路径中的 "\\" 可以换成 '/',但不能是 '\'
同理,我们也可以用 fclose(stdin); 来关闭该输入流,但同输出流一样,应该放到程序结尾出:
#include<stdio.h>
#define FILENAME "Input.txt"
int main()
{
freopen(FILENAME,"r",stdin);//读文件
char s\[100\];
while (scanf("%s", s) != EOF)
puts(s);
fclose(stdin);//放到程序结尾处
return 0;
}
#include <iostream>
int main() {
// 重定向标准输入到文件
freopen("example.txt", "r", stdin);
std::string line;
// 逐行读取文件内容
while (std::getline(std::cin, line)) {
// 处理每一行内容
std::cout << line << std::endl;
}
return 0;
}
2.2 使用fstream
•C++中的文件读写-fstream
函数简介
C++中对文件操作需要包含头文件
- ofstream:写操作(output file stream)
- ifstream: 读操作(input file stream)
- fstream : 读写操作(file stream)
写文件
步骤
- 创建流对象:ofstream ofs;
- 打开文件:ofs.open("文件名/文件路径",打开方式);
- 写数据:ofs << "写入的数据"; (将 cout 改为 ofs)
- 关闭文件:ofs.close();
文件打开方式
- ios::out :为写文件而打开文件
- ios::app :追加方式写文件
在代码所在的文件夹下新建一个 FILEC++.txt 文件,添加如下数据:
并运行如下代码:
#include<iostream>
#include<fstream>//包含头文件
using namespace std;
#define FILENAME "FILEC++.txt"
void write()
{
ofstream ofs;//创建流对象
ofs.open(FILENAME, ios::out);//打开文件
ofs << "测试向FILEC++.txt中写文件" << endl;//写数据
ofs.close();//关闭文件
}
int main()
{
write();
return 0;
}
打开 FILEC++.txt 查看文件内容变化。
你会发现,通过 ios::out 方式打开文件,之前的内容被覆盖了。
更改文件打开方式:
void write()
{
ofstream ofs;//创建流对象
ofs.open(FILENAME, ios::app);//打开文件
ofs << "测试向FILEC++.txt中写文件-2.0" << endl;//写数据
ofs.close();//关闭文件
}
查看 FILEC++.txt 中的内容:
可以测试出, ios::app 是在原文件的基础上向后追加内容。
由于是通过创建 ofs 来进行写文件操作,那么原本的输出语句就不会报错。
#include<iostream>
#include<fstream>//包含头文件
using namespace std;
#define FILENAME "FILEC++.txt"
void write()
{
ofstream ofs;//创建流对象
ofs.open(FILENAME, ios::out);//打开文件
ofs << "测试向FILEC++.txt中写文件" << endl;//写数据
ofs.close();//关闭文件
}
int main()
{
cout << "TEST1 : Hello World" << endl;
write();
cout << "TEST2 : Hello World" << endl;
return 0;
}
运行结果:
FILEC++.txt :
可见,通过 ofstream 来进行写文件操作,并不会影响 cout 的输出。
读文件
步骤
- 创建流对象: ifstream ifs;
- 打开文件: ifs.open("文件路径",打开方式);
- 判断文件是否打开成功: ifs.is_open() (成功打开返回 true,否则返回 false)
- 读数据: ifs >> 变量1 >> 变量2 >> ...; (类比 cin)
- 关闭文件: ifs.close();
使用流提取操作符(>>)
使用流提取操作符可以按照数据类型从文件中逐个读取数据。例如,可以使用>>操作符从文件中读取整数、浮点数、字符串等。
下面是使用流提取操作符读取文件内容的示例:
示例:
在当前代码所在文件夹下新建一个 Input.txt 的文件,并放入如下数据:
分别代表:编号、姓名、年龄,并用 id , name , age 接受这三个数据。
#include<iostream>
#include<fstream>//包含头文件
using namespace std;
#define FILENAME "Input.txt"
void read()
{
ifstream ifs;//创建流对象
ifs.open(FILENAME, ios::in);//打开文件
int id;
string name;
int age;
if (!ifs.is_open())//判断文件是否打开成功
{
cout << "文件打开失败" << endl;
return;
}
ifs >> id >> name >> age;//读数据,且 编号、姓名、年龄 要和文件中的数据保持一致
cout << "编号\t姓名\t年龄" << endl;
cout << id << "\t" << name << "\t" << age << endl;
ifs.close();//关闭文件
return;
}
int main()
{
read();
return 0;
}
运行结果:
使用getline()函数
getline()函数可以按行从文件中读取数据,并存储到字符串中。它可以读取包含空格的一整行数据。
下面是使用getline()函数读取文件内容的示例:
#include <fstream>
#include <iostream>
int main() {
std::ifstream inputFile("example.txt");
if (inputFile.is_open()) {
std::string line;
// 逐行读取文件内容
while (std::getline(inputFile, line)) {
std::cout << line << std::endl;
}
inputFile.close();
} else {
// 文件打开失败,进行错误处理
std::cout << "无法打开文件进行读取操作。" << std::endl;
}
return 0;
}