繁体   English   中英

fstream::write 和 fstream::read 改变读写指针

[英]fstream::write and fstream::read changing both reading and writing pointers

我正在学习如何在文件中写入记录并阅读它。
我创建了一个名为student的类,该类具有enterStudentshowStudentprintInsideFile (student info) 、......等功能。
当我尝试将学生信息写入文件时,它可以工作。
当我尝试从文件中读取所有学生信息时,它可以工作
当我尝试两者都做时,会发生一些意想不到的事情(什么都没有出现)

我认为file.flush()的问题,所以当我删除它时,输出是不可读的文本
我可以关闭文件并再次打开它,但我认为这很愚蠢
代码是:

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


using namespace std;

class student {
private:
    char id[5], name[20], age[5], address[50], gender[5];
public:
    void enterStudent() {
        cout << "Enter student id : "; cin >> id;
        cout << "\nEnter student name : "; cin >> name;
        cout << "\nEnter student age : "; cin >> age;
        cout << "\nEnter student address : "; cin >> address;
        cout << "\nEnter student gender : "; cin >> gender;

    }
    void showStudent() {
        cout << "#########student data##########\n";
        cout << "student id : "<< id;
        cout << "\nstudent name : " << name;
        cout << "\nstudent age : " << age;
        cout << "\nstudent address : " << address;
        cout << "\nstudent gender : " << gender<<endl;
    }
    void printInsideFile(fstream &file) {
        file.write(id,sizeof(id));
        file.write(name, sizeof(name));
        file.write(age, sizeof(age));
        file.write(address, sizeof(address));
        file.write(gender, sizeof(gender));
        file.flush();
    }
    bool readFromFile(fstream &file) {
        if (file.eof())
            return 0;
        file.read(id, sizeof(id));
        file.read(name, sizeof(name));
        file.read(age, sizeof(age));
        file.read(address, sizeof(address));
        file.read(gender, sizeof(gender));
        if (file.eof())
            return 0;
        return 1;
    }
    void showAllFromFile(fstream &file) {
        while (this->readFromFile(file)) 
            this->showStudent();
    }
};

int main() {
    student s;
    fstream file;

    file.open("a.txt", ios::in | ios::out | ios::app);
    if (!file)
        goto k270;
    
    s.enterStudent();
    s.printInsideFile(file);

    //when i read one student , it works okay

    //s.readFromFile(file);
    //s.showStudent();

    //when i try to read multiple students , it doesn't work at all
    s.showAllFromFile(file);




    file.close();


k270:
    system("pause");
    return 0;
}

问题在于 ios::app

似乎函数file.write()file.read()改变了读取指针和写入指针。
即使你使用file<<"text"; file>>array of chars; 两个指针都在变化。

我搜索了它,但没有找到解释,但我找到了ostream::writeistream::read的代码,它们是先进的,所以如果有人检查链接并告诉我们原因

请注意,当读取指针指向文件末尾时,它不会打印任何内容

考虑到我对std::ios::app的经验最少,我很想知道它是如何工作的。

在 coliru 上做了以下 MCVE ,(我相信)它按 OP 的预期工作:

#include <fstream>
#include <iostream>

int main()
{
  // open a text file
  std::fstream file("test.txt", std::ios::in | std::ios::out | std::ios::app);
  // remember current position of read head
  file.seekg(0, std::fstream::end); // a trick to update the read head before writing anything
  std::fstream::pos_type pos0 = file.tellg();
  std::cout << "pos0: " << pos0 << '\n';
  // write a line to end of text
  std::cout << "Write a line.\n";
  file << "A line written by main.cpp" << std::endl;
  std::cout << "pos after writing: " << file.tellg() << '\n';
  // rewind to remembered position of read head
  file.seekg(pos0);
  // read the last written line
  { std::string buffer; std::getline(file, buffer);
    std::cout << "Last line: '" << buffer << "'\n";
  }
  // rewind to the beginning of file
  file.seekg(0);
  // read all
  std::cout << "Read all:\n";
  for (std::string buffer; std::getline(file, buffer);) {
    std::cout << "'" << buffer << "'\n";
  }
}

测试会话:

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp \
  && echo -e "1st line written by echo\n2nd line written by echo\n3rd line written by echo" > test.txt \
  ; ./a.out
pos0: 75
Write a line.
pos after writing: 102
Last line: 'A line written by main.cpp'
Read all:
'1st line written by echo'
'2nd line written by echo'
'3rd line written by echo'
'A line written by main.cpp'

笔记:

  1. 我完全确定file.seekg(0)read all读取之前需要将读取的文件头倒回到文件的开头。

  2. 我不确定read the last written line的内容……
    我发现file.seekg(pos0); 有必要的。
    显然,之前的写入似乎触及了写头(当然)以及读头。

  3. 我在使用std::istream::tellg()检索正​​确的读取头位置时遇到了一些麻烦。 它在第一个文件输出之后而不是之前返回了预期值。
    我最后的手段是file.seekg(0, std::fstream::end); 在写入任何内容之前将读取头移动到文件末尾。

  4. 对于示例中完全没有任何错误检查,我深表歉意。
    当然,这必须在严肃的应用程序中添加。
    我省略了它以使示例代码尽可能少。
    此外,我不认为错误处理是 OP 示例代码中的问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM