fstream::tellg() 和 ::seekg() 的问题

Posted

技术标签:

【中文标题】fstream::tellg() 和 ::seekg() 的问题【英文标题】:Issue with fstream::tellg() and ::seekg() 【发布时间】:2013-12-28 00:20:25 【问题描述】:

编辑

存在解决方案 - 使用 std::ios::binary 而不是以文本模式打开文件(尽管文件是纯文本)解决了该问题。 tellg() 现在报告正确的位置,因此 seekg() 现在可以用于返回相同的位置。

结束编辑

不久前,我们遇到了服务器问题。主服务器很好,但辅助服务器有点小问题。我们想知道在此期间是否有任何不同的记录。

我们知道日志文件之间存在 other 差异这一事实 - 它们的长度不同,因为当一个或另一个较早时发生日志记录。因此,我们不能进行直线逐行比较——我们可能会得到数千行,这些行被报告为不同的记录,但只是被顶部附近的一台服务器额外记录的两行抵消,而没有被记录另一个。

我正在编写一个程序来根据时间戳比较输出文本文件;也就是说,转到发生打嗝的时间戳周围的区域,并仅针对该区域逐行比较。这就是tellg() 和 seekg() 出现问题的地方。

首先,这个循环对两个日志文件都运行:

while( getline(inputFile, inputLine) && loopBreak != 1 && inputFile.good() )

    if (firstOpen.empty())

        if ( -1 != inputLine.find("TimeOfFirstEntry") )

            firstOpen = inputLine;
        
    

    if (!firstOpen.empty() && lastOpen.empty())

        if ( -1 != inputLine.find("TimeOfLastEntry") )

            lastOpen = inputLine;
        
    

    if (!firstOpen.empty() && !lastOpen.empty())

        if ( -1 != inputLine.find(timeStamp) )

            if (0 == firstLineInBucket)

                firstLineInBucket = inputFile.tellg();
                lastLineInBucket = inputFile.tellg();
            
            else

                lastLineInBucket = inputFile.tellg();
            
        

        if ( (0 != firstLineInBucket) && (0 != lastLineInBucket) )

            if ( (-1 != inputLine.find("OccuranceTime") ) && (-1 == inputLine.find(timeStamp)) )

                loopBreak = 1;
            
        
    

稍后,这个循环进行比较:

if(inputPrimary.good() && inputSecondary.good() && output.good())

    inputPrimary.seekg(Primary.getFirstBucket());
    inputSecondary.seekg(Secondary.getFirstBucket());

    std::string linePrimary;
    std::string lineSecondary;

    while(  getline(inputPrimary, linePrimary)
            && getline(inputSecondary, lineSecondary)
            && (inputPrimary.tellg() < Primary.getLastBucket())
            && (inputSecondary.tellg() < Secondary.getLastBucket()) )

        if(linePrimary == lineSecondary)

            //Do nothing
        
        else

            output << linePrimary << " .:|:. " << lineSecondary << "\n";
        
    

inputPrimary.close();
inputSecondary.close();
output.close();

这就是事情变得奇怪的地方:当我在一对文件上运行这个已知良好的时间戳(也就是说,它们都具有该时间戳的相同内容)时,内容被写入输出文件。进一步调查显示,在两个文件中报告写入的行不同,因为对于辅助服务器日志文件,seekg() 操作将位置放在行的开头,但对于主服务器日志文件,seekg () 操作将位置放置在距离最后一个换行符更远的位置 ~11 个字符。

到底是什么原因造成的?

【问题讨论】:

您使用什么类型来存储偏移量? 13 GB 将溢出 32 位类型。位置是完全错误的,还是真的只有 11 个字符? 当您使用它时,只需使用std::istream::pos_type。它甚至不是一个裸整数。 1.包括相关的声明和数据类型。 2. 提及它应该如何工作的理论,而不仅仅是目标是什么(这也有点模糊)。 3. 简化为可重现的测试用例。 4. 添加cmets。问题很可能出现在您的代码中,因为回溯到文件中的某个点已经过很好的测试。 【参考方案1】:

任何好的diff 程序都会向您展示不同的块。然后,您可以将结果加载到图形比较程序中,直观地扫描结果,忽略您知道不同的块,然后当你碰到意想不到的块时尖叫。

例如,WinMerge

(来源:majorgeeks.com)

【讨论】:

@medivh:这听起来不像是保存日志文件的实用方法。 @medivh 这是什么,healthcare.gov?无论如何,只要您不尝试将所有内容都保存在内存中,现在 13 GB 是一个非常易于处理的文件大小。你肯定找不到没有的差异程序。 "我的字面意思是'字面意思'" @medivh:它应该被分割成更小的文件。很明显。 @medivh:FDA 是否批准了您的 seekg()/tellg() 代码不起作用?【参考方案2】:

(是的,相对搜索不适用于以文本模式打开的文件) -Cubbi

所以答案就出来了 - 在 std::ios::binary 模式下打开可以很好地解决问题。

【讨论】:

但是发布的代码没有使用相对搜索。如果有,那将是主要嫌疑人。

以上是关于fstream::tellg() 和 ::seekg() 的问题的主要内容,如果未能解决你的问题,请参考以下文章

seek to time in mp4

python 文件操作seek() 和 telll() 自我解释

seek()和tell()在文件里转移

SQL Server中SCAN 和SEEK的区别

poj 2752 Seek the Name, Seek the Fame

Seek the Name, Seek the Fame POJ - 2752(拓展kmp)