C++笔记 01文件流操作

1 基本概念

文件 (file)

存储在磁盘上的数据集合,可以是文本、二进制等格式,具有名称、大小、类型等属性。

流 (stream)

一连串的字节,是一种抽象的数据传输方式。

在C++中,文件操作是基于流的概念,有3种主要类型的流:

  • 输入流 (istream):允许程序从源(如键盘、文件)读取数据。
  • 输出流 (ostream):允许程序将数据发送到目标(如显示器、文件)。
  • 输入/输出流 (iostream):结合了输入流和输出流的功能。

2 文件操作

使用#include <fstream>处理文件的输入输出。

ifstream:输入文件流,用于从文件中读取数据。

ofstream:输出文件流,用于向文件写入数据。

fstream:结合ifstream和ofstream功能,支持读写文件。


3 基本使用方法

3.1 包含必要的头文件

#include <fstream>
#include <iostream>
#include <string>

3.2 操作步骤

1)定义文件流

想使用文件流对文件进行操作,需要先定义它。

// there are 3 ways to define filestream
// 1) declare input stream
ifstream inFile;

// 2) declare output stream
ofstream outFile;

// 3) declare input&output stream
fstream file;
2)打开文件

进行文件操作之前,需要先打开文件。

打开文件:void open(const char *filename, ios::openmode mode);

filename:待打开文件的名称和位置

mode:文件被打开的模式

常用打开模式:

modeDescription
ios::in打开文件用于读取。
ios::out打开文件用于写入。
ios::trunc若文件已经存在,则在打开文件之前清空其内容,即把文件长度设为 0。
ios::app追加模式。所有写入都追加到文件末尾。
ios::ate文件打开后定位到文件末尾。
ios::binary二进制方式(默认是文本方式)
ios::nocreate不创建的方式
ios::norepalce不替换
inFile.open("file.txt",ios::in); //读取文件中的数据

outFile.open("file2.txt",ios::out|ios::trunc); //写数据进文件中

file.open("file.txt"); //读写文件中的数据(无参数即默认方式打开)

// 判断文件是否打开成功
if(!file.is_open())
{
    cout<<"file open failed!"<<endl;
    exit(-1);
}
3) 读写文件

使用流运算符>><< 分别进行读取和写入。(适用于文本形式)

// read
string dataBuffer;
inFile >> dataBuffer;

// write
outFile << "Hello World!" <<endl;

使用read()write()分别进行读取和写入。(适用于二进制形式)

istream & read(char* buffer, int count);

ostream & write(char* buffer, int count);

buffer:指定起始位置

count:字节个数

class Student
{
  char name[20];
  int age;
};
Student stu;

// read
ifstream inFile("test.dat",ios::in|ios::binary);
if(!inFile)
{
    exit(-1);
}
while(inFile.read((char*)&stu, sizeof(stu)))//一直读到文件结束
{
    cout << stu.name << "" << stu.age << endl;
}
// gcount()

// write
/*
    调用 write()函数时并没有指定这些字节写入文件中的具体位置。
    事实上,write()会从 文件写指针 指向的位置将二进制数据写入。
文件写指针:
    是ofstream/fstream对象内部维护的一个变量, 文件刚打开时,指向文件的开头.
    (如果以 ios::app 方式打开,则指向文件末尾)
    用 write() 方法写入 n 个字节,写指针指向的位置就向后移动 n 个字节。
*/
ofstream outFile("test.dat",ios::out|ios::binary);
while(cin >> stu.name >> stu.age)
{
    outFile.write((char*)&stu, sizeof(stu));
}

使用get()put()分别进行读取和写入。(适用于逐个读写)

int get();
istream& get (char& c);

ostream& put (char c);

char c;

// read
while( (c=inFile.get()) && c!=EOF) // while(inFile.get(c)){}
{//EOF:输入的末尾
    cout << c;
}

// write
while(cin >> c)
{
    outFile.put(c);
}

getline()读取一行

istream & getline(char* buf, int bufSize);

读取buf-1个字符,读到\n为止(不包括\n)

istream & getline(char* buf, int bufSize, char delim);

读到delim字符为止(不包括delim)

// read line
string lineBuffer;
getline(inFile, lineBuffer);//从文件中读取一行数据,将读到的数据写入lineBuffer

// 
char c[40];
inFile.getline(c,40);
cout << c;

//
inFile.getline(c,40,'end');
cout << c;

//多行
while(inFile.getline(c,40))
{
    cout << c <<endl;
}
4) 关闭文件

使用close()关闭文件,确保所有资源被释放。

或,当ifstreamofstreamfstream对象被销毁时,它们的析构函数会关闭文件。

inFile.close();
outFile.close();
file.close();
5)错误处理

使用以下方法检查文件流的状态:

  • good():无错误
  • eof():到达文件末尾
  • fail():非致命I/O错误
  • bad():致命I/O错误
if (inFile.good()) 
{
    // 继续处理文件
} 
else if (inFile.eof()) 
{
    cerr << "到达文件末尾" << endl;
} 
else if (inFile.fail()) 
{
    cerr << "非致命I/O错误" << endl;
} 
else if (inFile.bad()) 
{
   cerr << "致命I/O错误" << endl;
}

3.3 文件指针

可使用文件指针,移动文件内的读写位置:

  • seekg:设置输入位置
  • seekp:设置输出位置
  • tellg:获取输入位置
  • tellp:获取输出位置
// seekg和seekp:第一个参数指定位置,第二个参数指定查找方向
inFile.seekg(n); //定位到inFile的第n个字节(默认是ios::beg,即从流的开头开始定位)
inFile.seekg(n,ios::cur); //把文件的读指针从当前位置向后移n个字节
inFile.seekg(n,ios::end); //把文件的读指针从末尾往回移n个字节
inFile.seekg(0,ios::beg); //定位到文件开头
inFile.seekg(0,ios::end); //定位到文件末尾


// 获取文件大小
inFile.seekg(0,ios::end);
streampos size = inFile.tellg();

3.4 缓冲区

缓冲区类型:

  1. 全缓冲
    • 当填满标准I/O缓存后,进行实际I/O操作。
    • 典型代表:对磁盘文件的读写。
  2. 行缓冲
    • 当在输入和输出中遇到换行符时,进行实际I/O操作。
    • 此时,输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。
    • 典型代表:键盘输入数据。
  3. 不带缓冲
    • 不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

C++之ofstream::flush与ofstream::close_ofstream flush-CSDN博客

3.5 跳过(忽略)指定字符

istream & ignore(int n =1, int delim = EOF);

跳过输入流中的 n 个字符,或跳过 delim 及其之前的所有字符,哪个条件先满足就按哪个执行。

两个参数都有默认值,因此 cin.ignore() 就等效于 cin.ignore(1, EOF), 即跳过一个字符。

int n;
cin.ignore(5, 'A');
cin >> n;
cout << n;
//cin.ignore() 跳过了输入中的前 5 个字符,其余内容被当作整数输入 n 中
abcde34↙
34

//cin.ignore() 跳过了输入中的 'A' 及其前面的字符,其余内容被当作整数输入 n 中
abA34↙
34
  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值