C++读和写文件操作说明
一、 C++读和写文件操作说明
文章目录
1、打开方式
fstream头文件中,有三个主要的类分别是:
- fstream: 读写文件
- ifstream: 读文件 // input (文件数据输入到内存)
- ofstream: 写文件 // output (内存数据输出到文件)
每个类的对象可以调用下面几个常用的函数:
- open(“文件/文件路径”,打开方式)
- is_open() //判断这个文件是否被打开
- close() //关闭打开的文件
打开文件
在对文件进行读写操作之前,先要打开文件。打开文件有以下两个目的:
- 通过指定文件名,建立起文件和文件流对象的关联,以后要对文件进行操作时,就可以通过与之关联的流对象来进行。
- 指明文件的使用方式。使用方式有只读、只写、既读又写、在文件末尾添加数据、以文本方式使用、以二进制方式使用等多种。
打开文件可以通过以下两种方式进行:
- 调用流对象的 open 成员函数打开文件。
- 定义文件流对象时,通过构造函数打开文件。
总结:打开文件的方法有两种方式,一个是使用流类的构造函数打开文件,另一个采用open成员函数打开文件
- ios::in //为输入(读)而打开文件 文件以输入方式打开(文件数据输入到内存)
- ios::out //为输出(写)而打开文件,ofstream,默认的打开方式 文件以输出方式打开 (内存数据输出到文件)
- ios::ate //初始位置:文件尾
- ios::app //所有输出附加在文件末尾,用追加的方式添加
- ios::truc //如果文件已存在则先删除文件
- ios::binary //二进制方式
表1:文件打开模式标记
模式标记 | 适用对象 | 作用 |
---|---|---|
ios::in | ifstream fstream | 打开文件用于读取数据。如果文件不存在,则打开出错。 |
ios::out | ofstream fstream | 打开文件用于写入数据。如果文件不存在,则新建该文件;如果文件原来就存在,则打开时清除原来的内容。 |
ios::app | ofstream fstream | 打开文件,用于在其尾部添加数据。如果文件不存在,则新建该文件。 |
ios::ate | ifstream | 打开一个已有的文件,并将文件读指针指向文件末尾(读写指 的概念后面解释)。如果文件不存在,则打开出错。 |
ios:: trunc | ofstream | 打开文件时会清空内部存储的所有数据,单独使用时与 ios::out 相同。 |
ios::binary | ifstream ofstream fstream | 以二进制方式打开文件。若不指定此模式,则以文本模式打开。 |
ios::in ios::out | fstream | 打开已存在的文件,既可读取其内容,也可向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。 |
ios::in ios::out | ofstream | 打开已存在的文件,可以向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。 |
ios::in ios::out | fstream | 打开文件,既可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容;如果文件不存在,则新建该文件。 |
ios::trunc | fstream | 打开文件,既可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容;如果文件不存在,则新建该文件。 |
注意事项:
- ios::binary 可以和其他模式标记组合使用,例如:
- ios::in | ios::binary表示用二进制模式,以读取的方式打开文件。
- ios::out | ios::binary表示用二进制模式,以写入的方式打开文件。
文本方式与二进制方式打开文件的区别其实非常微小。一般来说,如果处理的是文本文件,那么用文本方式打开会方便一些。但其实任何文件都可以以二进制方式打开来读写。
在流对象上执行 open 成员函数,给出文件名和打开模式,就可以打开文件。判断文件打开是否成功,可以看“对象名”这个表达式的值是否为 true,如果为 true,则表示文件打开成功。
** 网上补充版**
- ios::in:文件以输入方式打开(文件数据输入到内存)
- ios::out:文件以输出方式打开(内存数据输出到文件)
- ios::app:以追加的方式打开文件
- ios::ate:文件打开后定位到文件尾,ios:app就包含有此属性
- ios::trunc:如果文件存在,把文件长度设为0
- ios::binary:以二进制方式打开文件,缺省的方式是文本方式
- ios::nocreate:不建立文件,所以文件不存在时打开失败
- ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
2、实例代码
2.1 第一版代码
/* 2022 08 11 */
//预备知识
//fstream // 文件流
//ifstream // 输入文件流 in
//ofstream // 输出文件流 out
//ios::in:文件以输入方式打开(文件数据输入到内存)
//
//ios::out:文件以输出方式打开(内存数据输出到文件)
//
//ios::app:以追加的方式打开文件
//
//ios::ate:文件打开后定位到文件尾,ios:app就包含有此属性
//
//ios::trunc:如果文件存在,把文件长度设为0
//
//ios::binary:以二进制方式打开文件,缺省的方式是文本方式
//
//ios::nocreate:不建立文件,所以文件不存在时打开失败
//
//ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
第一版代码
```cpp
#include<iostream>
#include<fstream>
#include<ctime>
#include<string>
#include<sstream>
using namespace std;
void write_file()//写文件
{
srand((unsigned int)time(NULL));
ofstream file1;
file1.open("car.txt", ios::app); // 所有输出附加在文件末尾,用追加的方式写入,
// 写入追加的结果以换行的方式往下添加
if (file1.is_open())
{
cout << "正确打开文件! " << endl;
for(int i=0;i<10;i++)
file1 << rand() % 10 << endl;
}
file1.close();
}
void test02()//一行一行读文件
{
ifstream file2;
string _str;
file2.open("car.txt");
if (file2.is_open())
{
cout << "正确打开文件! " << endl;
//一行一行读
if (file2.is_open())
{
while (getline(file2, _str))//用法:接收一个字符串,可以接收空格并输出,需包含“#include<string>”
{
cout << _str << endl;
}
}
}
}
void test03() //文件写入(不追加,覆盖原文件)
{
//1、创建流对象
fstream file; //可输入输出
//2、指定打开方式
file.open("A.txt", ios::out);
//3、文件写入
file << "abc256"<<" " << 123<<endl;
file.close();
}
void test04() //测试将字符串与数字分开输出
{
//1、创建流对象
fstream file; //可输入输出
//ifstream file; //可输入
//2、指定打开方式
file.open("A.txt", ios::in);
//3、文件读取(前面是字符串,后面是数字)"abc256"123
string s;
int num;
if (file.is_open())
{
cout << "正确打开文件! " << endl;
while (file >> s >> num) //文件读取至末尾
{
cout << s << endl << num << endl;
}
}
file.close();
}
double my_atod(string tempString) //需要包含头文件 #include<sstream>
{
double result;
stringstream ss;
ss << tempString;
ss >> result;
return result;
}
void test05()
{
//1、创建流对象
fstream fs; //可输入输出 "123,456,789"
//2、指定打开方式
fs.open("stringNum.txt",ios::out);
//3、文件写入
fs << "123,456,789" << endl;
fs.close();
cout << "正确写入文件!" << endl;
}
void test06()//"123,456,789"
{
//1、创建流对象
fstream fs; //可输入输出
//2、指定打开方式
fs.open("stringNum.txt", ios::in);//ios::in:文件以输入方式打开(文件数据输入到内存)
cout << "打开文件前! " << endl;
//3、文件读取(前后都是数字)
if (fs.is_open())
{
cout << "正确打开文件! " << endl;
string line;//准备一个空字符串
string::size_type position;//写成int也行
position = 0;
while (getline(fs,line)) //文件读取一行,并按分隔符进行处理
{
cout << line << endl;
}
cout << "从字符串的第0位开始寻找" << endl;
//使用string::find函数的缺点:遇见','就会终止
//if ((position = line.find('1', position)) != string::npos) //如果没找到,返回一个特别的标志c++中用npos表示,我这里npos取值是4294967295,写成-1也行,计算机中和npos相等
//{
// cout << "position= " << position << endl;
//}
/* 查找字符串中的','*/
//char line1[] = { "123,456,7891455" };
//cout << "从字符串的第0位开始寻找" << endl;
//char *p = line1;
//while (*p != '\0')
//{
// if (*p == ',')
// {
// cout << "position= " << position << endl;
// }
// position++;
// p++;
//}
}
fs.close();
}
int main()
{
//write_file();
//test02();
//test03();
//test04();
test05();
test06();
}
2.2 第二版代码
/* 2022 08 11 */
//预备知识
//fstream // 文件流
//ifstream // 输入文件流 in
//ofstream // 输出文件流 out
//ios::in:文件以输入方式打开(文件数据输入到内存)
//ios::out:文件以输出方式打开(内存数据输出到文件)
//ios::app:以追加的方式打开文件
//ios::ate:文件打开后定位到文件尾,ios:app就包含有此属性
//ios::trunc:如果文件存在,把文件长度设为0
//ios::binary:以二进制方式打开文件,缺省的方式是文本方式
//ios::nocreate:不建立文件,所以文件不存在时打开失败
//ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败
// To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
// 在VS2013中,使用提示中的_CRT_SECURE_NO_WARNINGS,以下是使用方法:
// 1.项目属性—— > C / C++—— > 预处理器—— > 预处理器定义。
// 2. 点击后栏。
// 3.输入:_CRT_SECURE_NO_WARNINGS(与前面的要用分号分开,后面加分号)
//或者采用宏定义
#define _CRT_SECURE_NO_WARNINGS //出现安全警告 放置在头文件顶部
#include<iostream>
#include<fstream>
#include<ctime>
#include<string>
using namespace std;
void write_file1()//写文件
{
srand((unsigned int)time(NULL));
ofstream file1;
file1.open("car.csv", ios::app); // 所有输出附加在文件末尾,用追加的方式写入,
// 写入追加的结果以换行的方式往下添加
if (file1.is_open())
{
cout << "正确打开文件! " << endl;
for(int i=0;i<10;i++)
file1 << rand() % 10 << endl;
}
file1.close();
}
void read_file1()//一行一行读文件
{
ifstream file1;
string _str;
file1.open("car.csv");
if (file1.is_open())
{
cout << "正确打开文件! " << endl;
//一行一行读
if (file1.is_open())
{
while (getline(file1, _str,','))//用法:接收一个字符串,可以接收空格并输出,需包含“#include<string>”
{
cout << _str << endl;
}
}
}
}
void write_file2_NoAdd() //文件写入(不追加,覆盖原文件)
{
//1、创建流对象
fstream file; //可输入输出
//2、指定打开方式
file.open("A1.txt", ios::out);
//3、文件写入
file << "abc256JKJKKJ" << " " << 123 << endl;//中间要有空格才能识别字符串与数字
file.close();
}
void read_file2() //测试将字符串与数字分开输出
{
//1、创建流对象
fstream file; //可输入输出
//ifstream file; //可输入
//2、指定打开方式
file.open("A1.txt", ios::in);
//3、文件读取(前面是字符串,后面是数字)"abc256"123
string s;
int num;
if (file.is_open())
{
cout << "正确打开文件! " << endl;
while (file >> s >> num) //文件读取至末尾
{
cout << s << endl << num << endl;
}
}
file.close();
}
void write_file3()
{
//1、创建流对象
fstream fs; //可输入输出 "123,456,789"
//2、指定打开方式
fs.open("stringNum.txt",ios::out);
//3、文件写入
fs << "123,456,789" << endl;
fs.close();
cout << "正确写入文件!" << endl;
}
void read_file3()//"123,456,789"
{
//1、创建流对象
fstream fs; //可输入输出
//2、指定打开方式
fs.open("stringNum.txt", ios::in);//ios::in:文件以输入方式打开(文件数据输入到内存)
//cout << "打开文件前! " << endl;
//3、文件读取(前后都是数字)
if (fs.is_open())
{
cout << "正确打开文件! " << endl;
string line;//准备一个空字符串
string::size_type position;//写成int也行
position = 0;
while (fs >> line)
{
cout << line ;
}
//cout << line ;
//使用string::find函数的缺点:遇见','就会终止
//if ((position = line.find(',', position)) != string::npos) //如果没找到,返回一个特别的标志c++中用npos表示,我这里npos取值是4294967295,写成-1也行,计算机中和npos相等
//{
// cout << "从字符串的第0位开始寻找" << endl;
// cout << "position= " << position << endl;
//}
/* 查找字符串中的','*/
//使用测试数组
//char name_line[25] = { "123,456,7891455" };//使用字符数组
//char *p = name_line;
//cout << "从字符串的第0位开始寻找" << endl;
//while (*p != '\0')
//{
// if (*p == ',')
// {
// cout << "position= " << position << endl;
// }
// position++;
// p++;
//}
// c_str()函数 //这里还要重写
char ps[20]="aaaa";
strcpy(ps,line.c_str());
//cout << ps << endl;
cout << "从字符串的第0位开始寻找" << endl;
char *pd = ps;
while (*pd != '\0')
{
if (*pd == ',')
{
cout << "position= " << position << endl;
}
position++;
pd++;
}
}
fs.close();
}
void test07()
{
string s = "aaaavvva";
char a[10];
//strncpy_s(a, s.c_str(), s.length() + 1);//必须加1,\0还占一个位置
strcpy_s(a, s.c_str());//区分strncpy_s和strcpy_s
for (int i = 0; i < 10; i++)
cout << a[i] << " ";
cout << endl;
}
void test08()
{
//const char* c; //①
//char* c; //②
//char c[20];
char* c = new char[20];
string s = "1234";
//c = s.c_str();
strcpy(c, s.c_str());
cout << c << endl; //输出:1234
s = "abcd";
cout << c << endl; //输出:1234
}
int main()
{
//write_file1();//写文件
//read_file1();//一行一行读文件
//write_file2_NoAdd();//文件写入(不追加,覆盖原文件)
//read_file2();
write_file3();
read_file3();
//test07();
//test08();
}
二、补充部分 C++:cin、cin.getline()、getline()的用法
主要内容:
- cin用法
- cin.getline()用法
- getline()用法
注意的问题
1、cin>>
用法1:输入一个数字或字符
#include <iostream>
using namespace std;
int main ()
{
int a,b;
cin>>a>>b;
cout<<a+b<<endl;
}
用法2:接收一个字符串,遇“空格”、“TAB”、“回车”就结束
#include <iostream>
using namespace std;
int main ()
{
char a[20];
cin>>a;
cout<<a<<endl;
}
输入:jkljkljkl
输出:jkljkljkl
输入:jkljkl jkljkl //遇空格结束
输出:jkljkl
2、cin.getline()
用法:接收一个字符串,可以接收空格并输出
#include <iostream>
using namespace std;
int main ()
{
char m[20];
cin.getline(m,5);
cout<<m<<endl;
}
输入:jkljkljkl
输出:jklj
接收5个字符到m中,其中最后一个为’\0’,所以只看到4个字符输出;
如果把5改成20:
输入:jkljkljkl
输出:jkljkljkl
输入:jklf fjlsjf fjsdklf
输出:jklf fjlsjf fjsdklf
延伸:
1、cin.getline()实际上有三个参数,cin.getline(接收字符串的变量,接收字符个数,结束字符)
2、当第三个参数省略时,系统默认为’\0’
3、如果将例子中cin.getline()改为cin.getline(m,5,‘a’);当输入jlkjkljkl时输出jklj,输入jkaljkljkl时,输出jk
3、getline()
用法:接收一个字符串,可以接收空格并输出,需包含
#include<string>
示例代码
#include<iostream>
#include<string>
using namespace std;
int main ()
{
string str;
getline(cin,str);
cout<<str<<endl;
}
输入:jkljkljkl
输出:jkljkljkl
输入:jkl jfksldfj jklsjfl
输出:jkl jfksldfj jklsjfl