找到一条线末端位置的有效方法

时间:2012-03-08 15:58:44

标签: c++ ifstream end-of-line

我正在使用C ++,ifstream和文本文件。我正在寻找每行结尾的位置,因为我需要从行尾读取n个字符。

目前,我正在读取每个字节并测试它是否与Unix换行符(LF)相对应。

不幸的是,输入通常是长文本,我的方法也不快。

有没有更快的方法?

6 个答案:

答案 0 :(得分:6)

如果您正在寻找原始速度,我会将内存映射到文件并使用strchr之类的内容来查找换行符;

p = strchr(line_start, '\n');

然后只要p不是NULL或内存区域中的第一个字符,就可以使用p[-1]在换行符之前读取字符。

注意:如果文件可能包含'\0'个字符,那么您应该使用memchr。实际上,这可能是合乎需要的,因为它允许您指定缓冲区的大小(内存区域)。

答案 1 :(得分:2)

  

我正在使用C ++,ifstream和文本文件。我正在寻找每一行结尾的位置,因为我需要从行尾读取n个字符

我会专注于你的要求,从行尾读取'n'个字符,而不是你的问题:

// Untested.
std::string s;
while(std::getline(std::cin, s)) {
    if(s.size() > n) s.erase(s.begin(), s.end()-n);
    // s is the last 'n' chars of the line
    std::cout << "Last N chars: " << s << "\n";
}

答案 2 :(得分:1)

您可以查看std::string中的getline功能。尝试一次读取整行,然后从字符串末尾读取字符。

与性能问题一样,真正的诀窍是通过分析器运行代码以查看它花费时间的位置。 “最快”和“足够快”之间通常存在非常明显的区别。

答案 3 :(得分:1)

没有更简单的方法可以到达行标记的末尾,但是通过存储读取数据时读取的内容可以节省一些时间。你不需要回去,你的循环会非常快。

创建一个大小为n的字符数组,并将其用作循环缓冲区:当你到达数组的末尾时,只需回到它的开头即可。将字符存储在循环缓冲区的下一个位置。

当你检测到'\n'时,你的缓冲区包含n个先前字符,只是略有乱序:前缀从你的缓冲区指针开始并转到缓冲区的末尾,后缀开始在零处,并转到缓冲区指针减一。

以下是如何使其发挥作用的示例(假设n == 20):

int main()
{
    ifstream fs("c:\\temp\\a.txt");
    char buf[20];
    int bp = 0;
    bool circular = false;
    while (fs.good()) {
        char ch = fs.get();
        if (ch != '\n') {
            buf[bp] = ch;
            bp = (bp+1) % 20;
            circular |= !bp;
        } else {
            string s;
            if (circular) {
                s = string(buf+bp, buf+20) + string(buf, buf+bp);
            } else {
                s = string(buf, buf+bp);
            }
            cerr << s << endl;
            circular = false;
            bp = 0;
        }
    }
    return 0;
}

答案 4 :(得分:0)

快速&amp;肮脏的方式是这样的:

ifs.seekg( 0, std::ifstream::end );
std::string buffer( ifs.tellg(), '\0' );
ifs.seekg( 0, std::ifstream::beg );
ifs.read( &buffer[0], buffer.size() );

然后在缓冲区上工作。这可能会为您提供所需的全部速度(根据我的经验,可以达到许多数量级)。如果你想能够处理任意大的文件,你需要稍微修改一下逻辑(而不是用块搜索)。

答案 5 :(得分:0)

无论你做什么,你仍然最终会通过文件线性搜索 。您可能搜索速度更快,但仍然是线性搜索。

真正的解决方案是更改文件的格式,因此在文件开头附近写入“有趣”字符的索引。到了阅读它的时候,你可以完全跳过文件的“无趣”部分。

如果不可能,您可以生成单独的“索引”文件。这不会使您无需执行一次线性搜索,但可以避免在同一文件上重复执行此操作。这当然只有在你不止一次处理同一个文件时才有意义。

顺便说一句,即使是线性扫描也应该非常快。你应该比任何东西都更受I / O限制。您的文件有多大,“我的方法不快”是什么意思?