在阅读文本文件

时间:2017-07-10 14:41:22

标签: c++ windows file fstream seekg

我正在尝试使用此处描述的逻辑Fastest way to read only last line of text file?获取最后一行文件,但我得到了一些奇怪的异常:

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()偏移量-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(传递 CR LF 字节)。但是让我们考虑第一个char(从结尾)。

28 Mon Jul 10 16:11:24 2017

因此,流转到7。它将其提取出来,并移至 CR 字节。然后,如果在下一个循环迭代中我们将其-3偏移,我们将获得0,但不会1!但实际上,我得到了1!并且所有工作正常-3偏移。这对我来说是个谜。无法理解我的想法。

1 个答案:

答案 0 :(得分: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'。但是,当您搜索时,它只是将字节偏移量用于实际文件中。这就是为什么人们建议您从头到尾阅读文件,或者以二进制模式打开文件以删除这种二分法。