如何在C++中向文件的中间写入内容?

11

我认为这应该很简单,但我的谷歌搜索没有帮助到我... 我需要在C++中写入一个已存在的文件,但不一定要写在文件末尾。

我知道当我只想将文本附加到文件时,我可以在调用流对象的open时传递标志ios:app。然而,这仅允许我写入文件的末尾,而不是其中间的位置。

我编写了一个简短的程序来说明这个问题:

#include <iostream>
#include <fstream>

using namespace std;

int main () {

  string path = "../test.csv";

  fstream file;
  file.open(path); // ios::in and ios::out by default

  const int rows = 100;
  for (int i = 0; i < rows; i++) {
    file << i << "\n";
  }  

  string line;
  while (getline(file, line)) {
    cout << "line: " << line << endl; // here I would like to append more text to certain rows
  }


  file.close();

}

你可能想要使用一个索引文件库(比如GDBM)或者sqlite,甚至是一个完整的数据库(PostgreSQLMongoDB等)。 - Basile Starynkevitch
1
标准的文件更改方式:读取输入文件,处理数据,写入新的输出文件,成功后,用输出文件覆盖输入文件。虽然有一些“更快”的替代方法(比如ios::app),但并不适用于每种情况。 - stefaanv
6
这不是已经有成千上万次在这里被问过了吗? - Lightness Races in Orbit
确实,例如这里(虽然我知道这是个修辞问题)。 - wonko realtime
3个回答

16

您无法在文件中间插入内容,您必须将旧文件复制到新文件中,在复制到新文件时插入想要的内容。

否则,如果您打算覆盖现有文件中的数据/行,可以使用std::ostream::seekp()来确定文件中的位置。


9
仅供完整性说明:您无法向文件中间插入内容,但可以通过覆盖相同数量的字节来进行替换。 - Thomas Padron-McCarthy
请参考以下示例代码以完成进一步操作:https://dev59.com/w3E95IYBdhLWcg3wPrgI - Anil
2
基本上,你可以使用 seekp() 成员函数将文件指针移动到任何位置,然后开始写入。然而,在文件结束符(EOF)之前的任何写入操作都会替换掉旧数据。 - 911

5
您可以一直写到末尾,然后交换行直到它处于正确的位置。这是我所做的事情。这是之前test.txt文件的内容:
12345678
12345678
12345678
12345678
12345678

这是我的程序示例:
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

fstream& goToLine(fstream& file, int line){
    int charInLine = 10;  //number of characters in each line + 2
                          //this file has 8 characters per line

    int pos = (line-1)*charInLine;

    file.seekg(pos);
    file.seekp(pos);

    return file;
}

fstream& swapLines(fstream& file, int firstLine, int secondLine){
    string firstStr, secondStr;

    goToLine(file,firstLine);
    getline(file,firstStr);
    goToLine(file,secondLine);
    getline(file,secondStr);

    goToLine(file,firstLine);
    file.write(secondStr.c_str(),8);    //Make sure there are 8 chars per line
    goToLine(file,secondLine);
    file.write(firstStr.c_str(),8);

    return file;
}

int main(){
    fstream file;
    int numLines = 5; //number of lines in the file

    //open file once to write to the end
    file.open("test.txt",ios::app); 
    if(file.is_open()){
        file<<"someText\n"; //Write your line to the end of the file.
        file.close();
    }

    //open file again without the ios::app flag
    file.open("test.txt"); 
    if(file.is_open()){
        for(int i=numLines+1;i>3;i--){ //Move someText\n to line 3
            swapLines(file,i-1,i);
        }
        file.close();
    }

    return 0;
}

以下是更改后的test.txt文件内容:
12345678
12345678
someText
12345678
12345678
12345678

我希望这可以帮到您!

0
基于我对操作系统的基本知识,我认为这是不可能的。我的意思是说,使用当前的存储技术制作一个可以允许这种功能的操作系统并非不可能,但这样做总会导致分段中的空间浪费。
但我不知道是否有任何技术可以实现这一点。尽管某些基于云的数据库确实使用这种类型的功能(例如在文件中间插入内容),但它们是专门为该DBMS软件制作的,具有非常具体的目标硬件,并且它们可能还具有一些定制内核来执行此类任务。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接