C++随机访问⽂件
顺序访问⽂件
⼀个⽂件是由⼀个字节序列构成的。操作系统维护⼀个叫做⽂件指针(file pointer)的特殊标记,指向序列中的某个位置。读写操作都是在⽂件指针指向的位置进⾏。当⽂件打开时,⽂件指针被设置在⽂件开始位置。当读写数据时,⽂件指针会移动到下⼀个数据项。例如,如果使⽤get()函数读取⼀个字节,C++从⽂件指针指向的位置读出⼀个字节,⽂件指针会向前移动⼀个字节,如下图所⽰:
(注:前是向⽂件结尾的⽅向,⽽后是向⽂件开始的⽅向)
我们之前写过的程序都是顺读写数据的,即⽂件指针⼀直向前移动,这被称为顺序访问⽂件。如果⼀个⽂件以输⼊的⽅式打开,将从其⽂件开始位置向⽂件结尾读取数据。如果⼀个⽂件以输出⽅式打开,则从其开始位置(默认)或末尾位置(ios::app)开始⼀个接⼀个地写⼊数据项。
随机访问⽂件
顺序访问的问题在于,如果我们想要读取⼀个特定位置的字节,那么必须读取它前⾯所有的字节,这样做效率太低了。所以C++引⼊了随机访问⽂件的概念,也就是说可以任意地向前或向后移动⽂件指针,⽽使⽤的函数是seekp和seekg函数。
seekp,即seek put,⽤于输出流。
seekg,即seek get,⽤于输⼊流。
seekp和seekg都有两个版本,分别是有⼀个参数的和有两个参数的。
⼀个参数的:参数指出绝对位置,例如:
input.seekg(0);
output.seekp(0);
以上两句代码都将⽂件指针移动到了⽂件开始的位置。
两个参数的:第⼀个参数是长整数,指出偏移量,正数为向前,负数为向后;第⼆个参数被称为定位基址(seek base),指出偏移量是相对于哪个位置⽽偏移的。下表给出了三个⽀持的定位基址参数。
定位基址描述
ios::beg偏移量相对于⽂件开始位置
ios::end偏移量相当于⽂件结尾位置
ios::cur偏移量相当于⽂件指针当前位置
下表给出⼀些使⽤seekp和seekg函数的例⼦。
语句描述
seekg(100, ios::beg);将⽂件指针移动到从⽂件开始第100个字节处
seekg(-100, ios::end);将⽂件指针移动到⽂件末尾向后100个字节处
seekp(42, ios::cur);将⽂件指针从当前位置向前移动42个字节
seekp(-42, ios::cur);将⽂件指针从当前位置向后移动42个字节
seekp(100);将⽂件指针移动到⽂件第100个字节处
我们可以使⽤tellp和tellg函数返回⽂件指针的当前位置。
下⾯给出⼀个例⼦。这个例⼦先将4个Student对象写⼊到student.dat⽂件中。然后从student.dat⽂件中读取第三个同学的信息(⼀个Student 对象占据的空间是12,int=4,char=1,但是char占4):
#include <iostream>
#include <fstream>
using namespace std;
class Student {
public:
Student(){}
Student(char name, int age, int score){
this->age = age;
this->name = name;
this->score = score;
}
int getAge() const{
return this->age;
}
char getName() const{
return this->name;
}
int getScore() const{
return this->score;
}
private:
int age;
char name;
int score;
};
void displayStudent(const Student student){
cout << "学⽣" << Name() << "的年龄是" << Age() << ",成绩是" << Score() << endl; }
int main()
{
fstream binaryio;
binaryio.open("student.dat", ios::out|ios::binary);
Student student1('A', 10, 10);
Student student2('B', 11, 20);
Student student3('C', 10, 30);
Student student4('D', 12, 100);
binaryio.write(reinterpret_cast<char*>(&student1),sizeof(Student));
binaryio.write(reinterpret_cast<char*>(&student2),sizeof(Student));
binaryio.write(reinterpret_cast<char*>(&student3),sizeof(Student));
binaryio.write(reinterpret_cast<char*>(&student4),sizeof(Student));
binaryio.close();
binaryio.open("student.dat", ios::in|ios::binary);
Student studentNew;
binaryio.seekg(2*sizeof(Student));
cout << "当前⽂件指针的位置是" << llg() << endl;
displayStudent(studentNew);
cout << "当前⽂件指针的位置是" << llg() << endl;
binaryio.close();
return0;
}
运⾏结果:
student.dat⽂件:
sizeof 指针
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论