从文件C++中的特定位置读取

Mei*_*eir 5 c++ printing file offset

我有一个C++程序需要返回一个特定单词出现的行.例如,如果我的文件如下所示:

the cow jumped over
the moon with the
green cheese in his mouth
Run Code Online (Sandbox Code Playgroud)

我需要打印出"with"的行.所有程序获取的是从文件开头的偏移量(在这种情况下为24,因为"with"是从文件开头的24个字符).

如何打印整条线"月亮与",只有偏移量?

非常感谢!

ana*_*lyg 2

一个好的解决方案是从头开始读取文件直到所需的位置(由 @Chet Simpson 回答)。如果您想要优化(例如非常大的文件,位于中间的某个位置,典型的行相当短),您可以向后读取文件。但是,这仅适用于以二进制模式打开的文件(类 UNIX 平台上的任何文件;ios_base::binary在 Windows 上使用参数打开文件)。

算法如下:

  • 返回文件中的几个字节
  • 读取几个字节
  • 如果那里有行尾,剩下的就很简单了
  • 否则,重复

代码(在Windows上测试):

std::string GetSurroundingLine(std::istream& f, std::istream::pos_type start_pos)
{
    std::istream::pos_type prev_pos = start_pos;
    std::istream::pos_type pos;
    char buffer[40]; // typical line length, so typical iteration count is 1
    std::istream::pos_type size = sizeof(buffer);

    // Look for the beginning of the line that includes the given position
    while (true)
    {
        // Move back 40 bytes from prev_pos
        if (prev_pos < size)
            pos = 0;
        else
            pos = prev_pos - size;
        f.seekg(pos);

        // Read 40 bytes
        f.read(buffer, prev_pos - pos);
        if (!f)
            throw;

        // Look for a newline byte, which terminates previous line
        int eol_pos;
        for (eol_pos = sizeof(buffer) - 1; eol_pos >= 0; --eol_pos)
            if (buffer[eol_pos] == '\n')
                break;

        // If found newline or got to beginning of file - done looking
        if (eol_pos >= 0 || pos == (std::istream::pos_type)0)
        {
            pos += eol_pos + 1;
            break;
        }
    }

    // Position the read pointer
    f.seekg(pos);

    // Read the line
    std::string s;
    std::getline(f, s, '\n');

    return s;
}
Run Code Online (Sandbox Code Playgroud)

编辑:在类似 Windows 的平台上,行尾由 标记\r\n,因为您必须使用二进制模式,所以输出字符串将包含额外\r的字符(除非文件末尾没有行尾) ),你可以扔掉它。