打开以前截断的文件时出现奇怪的垃圾数据

时间:2010-06-25 18:31:16

标签: c++ ifstream garbage

在我的程序中,我已将stdout重定向到打印到'console.txt'文件。函数会像这样写入该文件:

void printToConsole(const std::string& text, const TCODColor& fc, const TCODColor& bc)
    {
        // write the string
        cout << text << "@";

        // write the two color values
        cout << static_cast<int>(fc.r) << " "
             << static_cast<int>(fc.g) << " " 
             << static_cast<int>(fc.b) << " "
             << static_cast<int>(bc.r) << " "
             << static_cast<int>(bc.g) << " " 
             << static_cast<int>(bc.b) << " " << endl;
    }

我有一个从该文件中读取的函数,如下所示:

    void Console::readLogFile()
    {
        ifstream log("console.txt", ifstream::in);
        if(!log.is_open())
        {
            cerr << "ERROR: console.txt not found!" << endl;
            return;
        }

        // read new input into Console
        string str;
        while(getline(log, str))
        {
            cerr << "str: " << str << endl;
            /* do stuff with str here */
        }
        cerr << endl;

        log.close();
        clearLogFile();
    }


    void Console::clearLogFile()
    {
        ofstream("console.txt", ios_base::trunc);
    }

第一次通过readLogFile,一切正常。然而,之后,它开始出现问题。它将在console.txt的第一行中读取为空字符串。我通过在gvim中打开console.txt来完成程序,并监视它是如何更改的。第一次,当它正常工作时,console.txt看起来像这样:

  1 moved UP.@191 191 191 0 0 0
  2 Player moved.@191 191 191 0 0 0
~
~

应该如此。然后程序转到clearLogFile,然后console.txt为空。但是,第二次,当我打开ifstream时,console.txt看起来像这样:

  1 ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
    ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@moved UP.@191 191 191 0 0 0
  2 Player moved.@191 191 191 0 0 0
~
~

这次,当getline将第一行读入str时,str为空。奇怪的是,cerr << "str: " << str << endl;行仍然将str打印为“向上移动。@ 191 191 191 0 0 0”,即使检查gdb中的str显示它是空的。

任何人都知道这里发生了什么?

1 个答案:

答案 0 :(得分:0)

正在写入的例程在重写文件之前没有重置它的文件位置。因此,它会在目标文件的偏移处开始。

我相信执行写操作后的cout.seekp(0)会重置写指针,从而重新启动文件开头的写操作。

但是,您可能会遇到很多问题,即日志文件内容与您使用它的方式的一致性。

评论在这里添加,因为我无法在评论框中进行格式化...

通过在每次写入后重置文件指针,输出文件中只会有一行。您需要确保在写入之前阅读它,否则新数据将被旧数据覆盖,或者更糟糕的是可能被部分覆盖。

e.g。写1:

Player moved 1 2 3 4

e.g。写2:

Player fell over

将离开:

Player fell over
3 4

在书面文件中,如果读者在作者第二次写作之前没有到达那里。

你可能最好使用显式文件,而不是使用cout,或者你可以记住读取之间的读取位置,并在执行下一次读取之前寻找它,但这会留下不断增长的日志文件。

HTH