覆盖一个已存在的文本文件 C++

6
这是我的另存为功能的工作原理 - 它会复制当前文件的行,直到到达第一个图形,然后使用我的打印方法打印图形的信息,最后关闭该标签。
std::ofstream newFile(filePath1_fixed, std::ios::app);
std::fstream openedFile(filePath);
std::string line1;
while (std::getline(openedFile, line1)) {
    if (line1.find("<rect") != std::string::npos
        || line1.find("<circle") != std::string::npos
        || line1.find("<line") != std::string::npos)
        break;
    newFile << line1 << std::endl;
}
figc.printToFile(newFile);
newFile << "</svg>\n";

我想问如何保存对当前文件所做的更改?我尝试了以下代码:

std::ifstream openedFile(filePath);
std::ofstream newFile(filePath, std::ios::app);
std::string line1;
std::string info_beg[100];
int t = 0;
while (std::getline(openedFile, line1)) {
    std::cout << "HELLYEAH";
    if (line1.find("<rect") != std::string::npos
        || line1.find("<circle") != std::string::npos
        || line1.find("<line") != std::string::npos)
        break;
    info_beg[t++] = line1;
}
for (int i = 0; i < t; i++)
    newFile << info_beg[i] << std::endl;
figc.printToFile(newFile);
newFile << "</svg>\n";

这是我能做到的最接近的翻译。我得到了这个结果:
  <?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>Example rect01 - rectangle with sharp corners</desc>

  <!-- Show outline of canvas using 'rect' element -->
  <rect x="1" y="1" width="1198" height="398"
        fill="none" stroke="blue" stroke-width="2" />

  <line x1="20" y1="100" x2="100" y2="20"
        stroke="red" stroke-width="2" />

  <rect x="20" y="30" width="40" height="50"
        fill="red" stroke="red" stroke-width="1" />

  <rect x="10" y="20" width="30" height="40"
        fill="red" stroke="blue" stroke-width="1" />

  <line x1="100" y1="200" x2="300" y2="400"
        stroke="red" stroke-width="2" />

  <circle cx="10" cy="20" r="30"
        fill="red" stroke="blue" stroke-width="2" />

</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="12cm" height="4cm" viewBox="0 0 1200 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <desc>Example rect01 - rectangle with sharp corners</desc>

  <!-- Show outline of canvas using 'rect' element -->
  <rect x="1" y="1" width="1198" height="398"
        fill="none" stroke="blue" stroke-width="2" />

  <line x1="20" y1="100" x2="100" y2="20"
        stroke="red" stroke-width="2" />

  <rect x="20" y="30" width="40" height="50"
        fill="red" stroke="red" stroke-width="1" />

  <rect x="10" y="20" width="30" height="40"
        fill="red" stroke="blue" stroke-width="1" />

  <line x1="100" y1="200" x2="300" y2="400"
        stroke="red" stroke-width="2" />

  <circle cx="10" cy="20" r="30"
        fill="red" stroke="blue" stroke-width="2" />

  <rect x="10" y="20" width="30" height="40"
        fill="red" stroke="blue" stroke-width="2" />

</svg>

所以我的实际问题是如何删除第一个标签或覆盖它,或者我需要采用不同的方法。

定义“保存更改到当前文件”。那是什么意思? - Sam Varshavchik
2
一种更安全的方法是编写一个新文件(如果需要,可以从原始文件复制),然后关闭两个文件,交换它们并删除旧文件。这被称为二阶段提交,自计算机发明以来一直是安全修改文件的方法。 - Richard Hodges
使用当前文件名作为构造函数参数的 ofstream 将覆盖它。 - Falla Coulibaly
你能解释一下为什么你选择使用 std::ios::app,如果你想要覆盖现有内容的话吗?是什么思维过程导致了这个决定? - Lightness Races in Orbit
2
@GeorgiGenchev:好的,靠猜测编程是行不通的。显然,根据其定义,std::ios::app 是错误的。因此,这不是一个解决方案。解决方案是不要同时尝试从同一文件读取和写入! - Lightness Races in Orbit
显示剩余3条评论
1个回答

21

请使用ios::trunc代替ios::app

std::ofstream的构造函数中使用std::ios::app会告诉程序在文件末尾追加内容而不是覆盖。如果您想要覆盖文件(即截断文件),那么使用std::ios::trunc会告诉程序覆盖现有文件。ofstream默认会这样做,因此您只需编写初始化代码:std::ofstream newFile(filePath);

此外,请不要尝试同时读写文件;这是行不通的。使用ifstream将数据读入缓冲区,然后使用close()关闭文件。然后,将newFile初始化为覆盖文件并将缓冲区内容写出。


OP需要更多的东西,因为它同时从同一个文件中获取要写入的数据。 - Lightness Races in Orbit
谢谢,这很有帮助。我成功地做到了,只需要关闭填充缓冲区的文件,然后声明ofstream即可。 - colos_enough
1
据我所知,ofstream 的默认行为是使用 std::ios::out,这与 trunc 不完全相同。out 不会删除原始内容,而是从开头开始覆盖。因此,如果新流比旧流短,则可能会出现包含新旧数据的文件的情况。 - mark sabido

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