读取并删除txt文件中的第一行(或最后一行),而不复制

我想读取并删除txt文件中的第一行(不复制,它是一个很大的文件)。
我看过网络,但每个人都只是把想要的内容复制到一个新文件中。我不能那样做。

以下是第一次尝试。此代码将被隐藏在循环中,因为没有删除任何行。如果代码将在每次打开时删除文件的第一行,则代码将到达末尾。

#include <iostream>
#include <string>
#include <fstream>
#include <boost/interprocess/sync/file_lock.hpp>

int main() {
    std::string line;
    std::fstream file;
    boost::interprocess::file_lock lock("test.lock");
    while (true) {
        std::cout << "locking
";
        lock.lock();
        file.open("test.txt", std::fstream::in|std::fstream::out);
        if (!file.is_open()) {
            std::cout << "can't open file
";
            file.close();
            lock.unlock();
            break;
        }
        else if (!std::getline(file,line)) {
            std::cout << "empty file
"; //
            file.close();                // never
            lock.unlock();               // reached
            break;                       //
        }
        else {
            // remove first line
            file.close();
            lock.unlock();
            // do something with line
        }
    }
}

解决方案

您想做什么确实不容易。

如果您不小心打开同一个文件进行读写,您最终将读取您刚刚写入的内容,结果将不会是您想要的结果。

就地修改文件是可行的:只需打开它,在其中查找,修改并关闭。但是,您希望复制文件的所有内容,文件开头的K字节除外。这意味着您必须以N字节为单位反复读写整个文件。

现在,一旦完成,K字节将保留在需要删除的末尾。我不认为有办法用溪流做到这一点。您可以使用unistd.h中的ftruncatetruncate函数,也可以使用Boost.Interprocesstruncate

这里有一个例子(没有任何错误检查,我允许您添加它):

#include <iostream>
#include <fstream>
#include <unistd.h>

int main()
{
  std::fstream file;
  file.open("test.txt", std::fstream::in | std::fstream::out);

  // First retrieve size of the file
  file.seekg(0, file.end);
  std::streampos endPos = file.tellg();
  file.seekg(0, file.beg);

  // Then retrieve size of the first line (a.k.a bufferSize)
  std::string firstLine;
  std::getline(file, firstLine);

  // We need two streampos: the read one and the write one
  std::streampos readPos = firstLine.size() + 1;
  std::streampos writePos = 0;

  // Read the whole file starting at readPos by chunks of size bufferSize
  std::size_t bufferSize = 256;
  char buffer[bufferSize];
  bool finished = false;
  while(!finished)
  {
    file.seekg(readPos);
    if(readPos + static_cast<std::streampos>(bufferSize) >= endPos)
    {
      bufferSize = endPos - readPos;
      finished = true;
    }
    file.read(buffer, bufferSize);
    file.seekg(writePos);
    file.write(buffer, bufferSize);
    readPos += bufferSize;
    writePos += bufferSize;
  }
  file.close();

  // No clean way to truncate streams, use function from unistd.h
  truncate("test.txt", writePos);
  return 0;
}

我真的希望能够为就地修改文件提供更干净的解决方案,但我不确定是否有这样的解决方案。

相关文章