在C ++中删除最后一行文件的最佳方法

时间:2014-01-13 00:28:07

标签: c++

我目前正在使用以下代码删除.txt文件的最后一行。它有效,但速度很慢。我该怎么做才能优化这段代码?

string line; 
vector<string> lines;
std::ifstream inputStream("example.txt");

while (getline(inputStream,line)) {
    lines.push_back(line);
}
inputStream.close();

std::fstream outputStream("example.txt", ios::out | ios::trunc);
if (outputStream.is_open())
{
    for (int i=0; i < lines.size()-2; i++)
    {
        outputStream << lines[i] << "\n";
    }
    outputStream.close();
}

3 个答案:

答案 0 :(得分:2)

有一些与操作系统相关的功能可以改变文件的大小。

在Unix世界中,使用truncate():http://linux.die.net/man/2/truncate

在Windows世界中,使用SetEndOfFile():http://www.google.com/search?btnI=1&q=msdn+SetEndOfFile

这两种技术都需要获取OS文件句柄并以这种方式使用文件进行dinking。如果你想这样做,我会编写一个带有文件名和新大小的函数。

这就留下了寻找新尺寸的问题。我认为从后面扫描有可能比从前面扫描更有效,但这对读者来说无论如何都是一种练习。

答案 1 :(得分:2)

无需在内存中缓冲整个文件。相反,您可以在阅读原始文件时写入第二个临时文件。写入第二个文件并关闭第一个文件后,可以将临时文件重命名为主文件(在UNIX上,一旦打开主文件,您也可以remove()并直接写入文件,打开它在remove() d)之后输入:

{
    std::ifstream in("example.txt");
    std::ofstream out("example.tmp");
    // some error checking...
    std::string line;
    std::getline(line);
    for (std::string tmp; std::getline(tmp); line.swap(tmp)) {
        out << line << '\n';
    }
    if (!out.close()) {
        // seems the output couldn't be written: deal with it somehow
    }
}
std::rename("example.tmp", "example.txt");

答案 2 :(得分:1)

根据文件的大小,您可能会发现从末尾(以块为单位)实际读取文件的速度更快,并保存最后一行的位置。然后,您可以将文件的一部分从头开始复制到所需的位置。这样,您就不必进行如此多的IO操作。

所以实际算法会是这样的:

  1. 打开文件
  2. 将读指针放在末尾 - chunkSize
  3. 读取 chunkSize 数据字节
  4. 如果有换行符,请存储位置,否则返回3.
  5. 将内容从开头复制到位置