【问题标题】:C++ - Find and replace in text file (standard system libraries)C++ - 在文本文件中查找和替换(标准系统库)
【发布时间】:2012-06-05 20:20:46
【问题描述】:

我正在寻求一些建议。

我的情况:

  • 应用程序使用文本本地文件

  • 在文件中有这样的标签:

    正确 = "TEXT"
    。不幸的是,正确=“TEXT”之间可以有无限的空格。
  • 获得的文本正在功能测试中,可能会被替换(更改必须存储在文件中)。

     正确 = "CORRECT_TEXT"

我目前的理论方法:

  • 使用 ofstream -- 逐行读取到字符串。

  • 查找标签并更改字符串。

  • 将字符串作为行保存到文件中。


在 C++ 中是否有一些简化方法(使用迭代器?)仅使用标准系统库(unix)。

感谢您的想法。

【问题讨论】:

  • 你的标题写着 C++ 你的标签写着 C 吗?这是两种不同的语言,你想要哪一种?
  • @JensGustedt 对不起——错误。请使用 C++。
  • 您目前的方法有什么不好?看起来很简单,反正ofstream是C++标准库的一部分。
  • 你是覆盖同一个文件还是生成一个新文件?
  • @Vlad 好的,谢谢。我想使用一个有效的解决方案。例如,我不知道是否可以在不使用辅助字符串的情况下直接在 ofstream 中查找和替换。

标签: c++ file text replace


【解决方案1】:

这是一个可能的解决方案:

例子:

#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <string>
#include <vector>

struct modified_line
{
    std::string value;
    operator std::string() const { return value; }
};
std::istream& operator>>(std::istream& a_in, modified_line& a_line)
{
    std::string local_line;
    if (std::getline(a_in, local_line))
    {
        // Modify 'local_line' if necessary
        // and then assign to argument.
        //
        a_line.value = local_line;
    }
    return a_in;
}

int main() 
{
    std::ifstream in("file.txt");

    if (in.is_open())
    {
        // Load into a vector, modifying as they are read.
        //
        std::vector<std::string> modified_lines;
        std::copy(std::istream_iterator<modified_line>(in),
                  std::istream_iterator<modified_line>(),
                  std::back_inserter(modified_lines));
        in.close();

        // Overwrite.
        std::ofstream out("file.txt");
        if (out.is_open())
        {
            std::copy(modified_lines.begin(),
                      modified_lines.end(),
                      std::ostream_iterator<std::string>(out, "\n"));
        }
    }

    return 0;
}

我不确定线条的操作应该是什么,但您可以使用:

编辑:

为避免一次将每一行存储在内存中,可以将初始 copy() 更改为写入备用文件,然后写入文件 rename()

std::ifstream in("file.txt");
std::ofstream out("file.txt.tmp");

if (in.is_open() && out.open())
{
    std::copy(std::istream_iterator<modified_line>(in),
              std::istream_iterator<modified_line>(),
              std::ostream_iterator<std::string>(out, "\n"));

    // close for rename.
    in.close();
    out.close();

    // #include <cstdio>
    if (0 != std::rename("file.txt.tmp", "file.txt"))
    {
        // Handle failure.
    }
}

【讨论】:

  • 我不确定modified_line 结构的用途是什么。不能直接用std::string吗?
  • @Matt,是的,你可以。 modified_line 结构可用于在从文件中读取后但在插入vector 之前更改行。我没有编写任何实际更改该行的代码,只是一个注释,因为我不确定所需的转换。
  • @hmjd 感谢您的帮助 :-)。我不创建临时文件真是太好了,但是对于大文件,我需要大量内存用于应用程序。 vector 的解决方案看起来不错:-)。
  • @Nanik,刚刚用替代方案更新了答案,该替代方案将使用临时文件并且任何时候只在内存中一行。
  • @hmjd 完美解决方案!我按照你的方法试试。非常感谢:-)。
【解决方案2】:

您可以将任务拆分成小块,并弄清楚如何在 C++ 中完成每一块:

  • 打开文件作为输入流
  • 将临时文件作为输出流打开
  • 从流中读取一行
  • 向流中写入一行
  • 将一行匹配到给定的模式
  • 替换一行中的文本
  • 重命名文件

注意:在这种情况下,您一次不需要在内存中存储超过一行。

【讨论】:

  • 谢谢 :-),我不需要太多内存真是太好了。
【解决方案3】:

它看起来很像“INI 文件”语法。你可以搜索它,你会有大量的例子。但是,其中很少有人会真正使用 C++ 标准库。

这里有一些建议。 (注意,我假设您需要替换的每一行都使用以下语法:&lt;parameter&gt; = "&lt;value_text&gt;"

  • 使用std::string::find 方法定位“=”字符。
  • 使用std::string::substr 方法将字符串拆分成不同的块。
  • 您需要创建一个修剪算法来删除字符串前面或后面的每个空白字符。 (可以用std函数来完成)

有了所有这些,您就可以拆分字符串并隔离各个部分以比较它们进行所需的修改。

玩得开心!

【讨论】:

  • 感谢您的帮助 :-),我试试看。
【解决方案4】:

您确定需要在 C++ 中执行此操作吗?由于您使用的是 Unix,因此您可以调用 sed,它可以使用以下命令轻松完成此操作:

cat oldfile | sed 's/\(correct *= *\)\"TEXT\"/\1\"CORRECT_TEXT\"/' > newfile

如果需要,您可以在 C++ 中调用 unix 命令(例如,使用 &lt;cstdlib&gt; 中的 system("command")

【讨论】:

  • 感谢您的帮助 :-)。我需要在应用程序中做,因为“TEXT”是由函数校正的(依赖于变量的值)。但是我可以将这个想法与调用系统命令一起使用,谢谢。
猜你喜欢
  • 2021-10-07
  • 2020-07-29
  • 2017-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-26
  • 2019-07-30
相关资源
最近更新 更多