fstream 使用格式化数据

fstream using formatted data

我是这个网站的新手,这是我的第一个问题! 我有一个关于 fstream 函数的问题。

fstream f("new.dat",ios::out|ios::in);

fstream既是输入又是输出,所以当我们这样使用它的时候,在它输出和输入之前有一个new.dat文件。但奇怪的是,当我这样做时,它会正确输出数据,但无法输入。 我发现如果你关闭它,然后重新打开它,它会输入。为什么会这样??

int main()
{
    fstream writeFile("newFile.dat", ios::out|ios::in);
    char i[3];
    char u[3]="HI";
    if (!writeFile)
    {
        cerr << "error" << endl;
    }
    writeFile << u <<endl;
    writeFile >> i;
    cout << i << endl;
}

这是我的完整代码,结果是一个空行。

fstream 对象在其输出文件中有一个位置,由于您打开它只是为了输出和输入而没有任何位置或书写修饰符,所以该位置在文件的末尾。当您将 i 输出到文件时,writeFilei 写入文件,然后将其位置移到 i 之后,因此当您要求它写入更多内容时,您不会t 覆盖 i.

您可以通过调用 writeFile.seekg(0) 将位置重置为文件的开头,这会将内部位置置于文件中的 0 位置(开头)。

如果您对流操作感到好奇,我建议您看看 cppreference.com and specifically its documentation on c++'s input and output libraries here

这里发生了一些事情:

  1. 如果文件不存在,您将无法打开进行读取,这包括您要读取和写入的文件。没有文件,没有打开。
  2. 一旦您设法打开文件,流就会跟踪它在文件中的位置。当您阅读或书写时,位置显然会移动。
  3. 流中只有一个位置标记,所以你可以读到你想写的地方,然后再写。不幸的是,这意味着任何进一步的阅读都将在写入之后进行。如果这不是你想要的,在写入之前获取并存储当前位置(使用 tellg),并在写入之后搜索(使用 seekg)到存储的位置。
    1. 这有一些问题,比如如果你想插入的数据块比你想覆盖的数据块长或短怎么办?这个问题的简单解决方案是读入缓冲区,编辑缓冲区,将缓冲区写回文件。
  4. 当您打开文件并开始向其中写入内容时,您将覆盖文件中的任何内容。如果要添加到文件,请使用 ios::app 打开。这会将流的位置设置为文件的末尾。我不知道有任何类型的插入会在您写入新数据时推动现有数据。

一些简单的文件处理示例代码

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

int main()
{
    fstream f1("filename", ios::out);
    if (f1.is_open())
    {
        if (f1 << "Hi")
        {
            cout << "wrote"<<endl;
        }
        f1.close();
    }
    fstream f2("filename", ios::out|ios::app);
    if (f2.is_open())
    {
        if (f2 << " there!")
        {
            cout << "appended"<<endl;
        }
        f2.close();
    }
    fstream f3("filename", ios::in);
    if (f3.is_open())
    {
        cout << f3.rdbuf()<< endl;
        f3.close();
    }

    fstream f4("filename", ios::in|ios::out);
    if (f4.is_open())
    {
        f4.seekg(3);
        if (f4 << "Fred!")
        {
            cout << "overwrote"<<endl;
        }
        f4.close();
    }

    fstream f5("filename", ios::in);
    if (f5.is_open())
    {
        cout << f5.rdbuf()<< endl;
        f5.close();
    }
// note the extra ! on the end left over from Hi there! I do not know how
// to get rid of this. I have always just done stuff like this to get around it.
    fstream f6("filename", ios::in);
    stringstream s1;
    string token;
    f6 >> token;
    s1 << token << " Tim!";
    f6.close();
    fstream f7("filename", ios::out);
    f7 << s1.rdbuf();
    f7.close();
// and then moved temp over filename.
    fstream f8("filename", ios::in);
    cout << f8.rdbuf()<< endl;
    f8.close();

}