c++文件I/O(781-788)

1.随机存取(cerr输出后exit(EXIT_FAILURE)会输出失败提示)

    这里的随机存取的意思是对一个文件我们指定任意位置进行读取,修改,删除等。这里我以之前生成的planet.dat为原本进行操作。

首先创建一个输入输出流对象,fstream包含输入和输出操作。

fstream finout; // read and write streams
finout.open(file,ios_base::in | ios_base::out | ios_base::binary);
这个file在这里就是planet.dat文件
然后是对指针进行移动,fstream提供的移动指针操作函数有seekg( )用于ifsream对象,seekp()用于ofstream对象,下面是seekg的原型

istream & seekg(streamoff, ios_base::seekdir);
istream & seekg(streampos);

一些例子:

fin.seekg(30, ios_base::beg); // 30 bytes beyond the beginning
fin.seekg(-1, ios_base::cur); // back up one byte
fin.seekg(0, ios_base::end); // go to the end of the file

beg是相对于文件开始出的偏移,cur是当前位置,end是文件末尾。第一个字节位置是0

seekg(0);//移到开头位置

代码段显示打开位置,移到开头位置并显示文件内容:

fstream finout; // read and write streams
    finout.open(file,ios_base::in | ios_base::out | ios_base::binary);
    //NOTE: Some Unix systems require omitting | ios::binary
    int ct= 0;
    if (finout.is_open())
    {
        finout.seekg(0); // go to beginning
        cout << "Here are the current contents of the "
             << file << " file:\n";
        while (finout.read((char *) &pl, sizeof pl))
        {
            cout << ct++ << ": " << setw(LIM) << pl.name << ": "
            << setprecision(0) << setw(12) << pl.population
            << setprecision(2) << setw(6) << pl.g << endl;
        }
        if (finout.eof())
            finout.clear(); // clear eof flag
        else
        {
            cerr << "Error in reading " << file << ".\n";
            exit(EXIT_FAILURE);
        }

对于其中的finout.eof()操作是因为当输入流读取文件内容到最后时,读到eof然后文件就将关闭禁止读写,所以使用clear()函数把流的状态重置,以便再次访问文件。

之后的操作是,我们将输入planet的结构体编号,然后再读取的时候根据     记录好*sizeof(p1)获得记录位置然后用seekg(place)移动。

    streampos place = rec * sizeof pl; // convert to streampos type
    finout.seekg(place); // random access

下面是完整的代码:

// random.cpp -- random access to a binary file
#include <iostream> // not required by most systems
#include <fstream>
#include <iomanip>
#include <cstdlib> // for exit()
const int LIM = 20;
struct planet
{
    char name[LIM]; // name of planet
    double population; // its population
    double g; // its acceleration of gravity
};
const char * file = "planets.dat"; // ASSUMED TO EXIST (binary.cpp example)
inline void eatline() { while (std::cin.get() != '\n') continue; }
int main()
{
    using namespace std;
    planet pl;
    cout << fixed;
    // show initial contents
    fstream finout; // read and write streams
    finout.open(file,ios_base::in | ios_base::out | ios_base::binary);
    //NOTE: Some Unix systems require omitting | ios::binary
    int ct= 0;
    if (finout.is_open())
    {
        finout.seekg(0); // go to beginning
        cout << "Here are the current contents of the "
             << file << " file:\n";
        while (finout.read((char *) &pl, sizeof pl))
        {
            cout << ct++ << ": " << setw(LIM) << pl.name << ": "
            << setprecision(0) << setw(12) << pl.population
            << setprecision(2) << setw(6) << pl.g << endl;
        }
        if (finout.eof())
            finout.clear(); // clear eof flag
        else
        {
            cerr << "Error in reading " << file << ".\n";
            exit(EXIT_FAILURE);
        }
    }
    else
    {
        cerr << file << " could not be opened -- bye.\n";
        exit(EXIT_FAILURE);
    }
    // change a record
    cout << "Enter the record number you wish to change: ";
    long rec;
    cin >> rec;
    eatline(); // get rid of newline
    if (rec < 0 || rec >= ct)
    {
        cerr << "Invalid record number -- bye\n";
        exit(EXIT_FAILURE);
    }
    streampos place = rec * sizeof pl; // convert to streampos type
    finout.seekg(place); // random access
    if (finout.fail())
    {
        cerr << "Error on attempted seek\n";
        exit(EXIT_FAILURE);
    }
    finout.read((char *) &pl, sizeof pl);
    cout << "Your selection:\n";
    cout << rec << ": " << setw(LIM) << pl.name << ": "
         << setprecision(0) << setw(12) << pl.population
         << setprecision(2) << setw(6) <<pl.g << endl;
    if (finout.eof())
        finout.clear(); // clear eof flag
    cout << "Enter planet name: ";
    cin.get(pl.name, LIM);
    eatline();
    cout << "Enter planetary population: ";
    cin >> pl.population;
    cout << "Enter planet's acceleration of gravity: ";
    cin >> pl.g;
    finout.seekp(place); // go back
    finout.write((char *) &pl, sizeof pl) << flush;
    if (finout.fail())
    {
        cerr << "Error on attempted write\n";
        exit(EXIT_FAILURE);
    }
    // show revised file
    ct = 0;
    finout.seekg(0); // go to beginning of file
    cout << "Here are the new contents of the " << file
         << " file:\n";
    while (finout.read((char *) &pl, sizeof pl))
    {
        cout << ct++ <<": " << setw(LIM) << pl.name << ": "
        << setprecision(0) << setw(12) << pl.population
        << setprecision(2) << setw(6) << pl.g << endl;
    }
    finout.close();
    cout << "Done.\n";
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值