1

我正在尝试获取文件的最后一行,使用此处描述的逻辑最快的方法来读取文本文件的最后一行?,但我得到了一些奇怪的异常:

score.seekg(-2, ios::cur);

将我的流重置为相同的字符,所以我得到无限循环。但是,将其设置为-3完美工作:

fstream score("high_scores.txt"); //open file

if(score.is_open()) //file exist
{   
    score.seekg(0, ios::end);

    char tmp = '~';
    while(tmp != '\n')
    {
        score.seekg(-3, ios::cur);

        if((int)score.tellg() <= 0) //start of file is start of line
        {
            score.seekg(0);
            break;
        }
        tmp = score.get();
        cout << tmp << "-";
    }
}

同样,问题是 - 此代码仅适用于seekg()offset -3,而理论上它应该适用于-2. 这可以以某种方式解释吗?文件内容是这样的(文件末尾的换行符):

28 Mon Jul 10 16:11:24 2017
69 Mon Jul 10 16:11:47 2017
145 Mon Jul 10 16:53:09 2017

我使用的是 Windows,所以现在我明白了为什么我需要-3从文件末尾偏移(以传递CRLF字节)。但是让我们考虑第一个字符(从结尾)。

28 Mon Jul 10 16:11:24 2017

因此,流到达7. 它提取它,并移动到CR字节。如果,那么,在下一次循环迭代中我们将它偏移-3,我们会得到0,但不是1!但实际上,我得到了1!并且在-3偏移量下一切正常。这对我来说是个谜。我无法摆脱它。

4

1 回答 1

2

我希望这能说明正在发生的事情:

28 Mon Jul 10 16:11:24 2017CL  <- C = CR, L = LF
                       6543210 <- position relative to ios::end
                        | || |
                        | || * Start after seekg(0, ios::end)
                        | *|   After first seekg(-3, ios::cur)
                        |  *   After first get()
                        *      After second seekg(-3, ios::cur)

当您寻找 时SEEK_END,您将流位置指针移动到文件末尾之后的字节。如果您寻找 -3,您将跳过 CR、LF,并最终在'7'. 您读取了这个字节,但这会将指针向前移动一个字节。然后你再往回走三,你最终在'0'.

请注意,文件中的行尾实际上是两个字节(CR 和 LF)。只是当您阅读它们时,它们被转换为单个'\n'. 然而,当你寻找它时,它只是在实际文件中使用字节偏移量。这就是为什么人们要么建议您从头到尾阅读文件,要么建议您以二进制模式打开文件以消除这种二分法。

于 2017-07-10T17:05:46.237 回答