【问题标题】:How to change a text file's name in C++?如何在 C++ 中更改文本文件的名称?
【发布时间】:2011-08-31 11:24:51
【问题描述】:

我想更改txt 文件的名称,但我找不到如何操作。

例如,我想在我的 C++ 程序中将 foo.txt 重命名为 boo.txt

【问题讨论】:

  • C++ 不直接支持文件系统。不同的操作系统为此功能提供不同的 API。你的目标是什么操作系统?
  • 这不是 C++ 题,只是可以打开一个文件名读取,打开另一个文件名写入,然后复制。更改名称是一项操作系统功能,因此您需要告诉我们您使用的是哪个操作系统,以便我们提供帮助。

标签: c++ algorithm file directory file-rename


【解决方案1】:

文件系统支持C++ 标准库中明显缺乏。正如 Jerry Coffin 的回答所示,stdio 中实际上有一个重命名功能(与我分享的普遍看法相反)。然而,标准库没有涵盖许多与文件系统相关的设备,因此存在 Boost::Filesystem(特别是操作目录和检索有关文件的信息)。

这是一个减少 C++ 约束的设计决策(即,可以在各种平台上编译,包括不存在文件概念的嵌入式系统)。

要执行文件操作,有两种选择:

  • 使用目标操作系统的API

  • 使用提供跨平台统一接口的库

Boost::Filesystem 就是这样一个 C++ 库,它可以抽象出平台差异。

您可以使用Boost::Filesystem::rename 重命名文件。

【讨论】:

    【解决方案2】:

    #include <stdio.h>(或<cstdio>)并使用rename(或std::rename):

    rename("oldname.txt", "newname.txt");
    

    与普遍的看法相反,它包含在标准库中,并且在一定程度上是可移植的——当然,字符串的允许内容会因目标系统而异。

    【讨论】:

      【解决方案3】:

      C++17 的<filesystem> 更新!

      多年后,我们在 C++ 标准中拥有 <filesystem>。 因此,其他帖子和cmets中提到的投诉“C++不直接支持文件系统”不再有效!

      支持 ISO 或更高版本的编译器,现在我们可以使用std::filesystem::rename 并执行以下操作:

      #include <filesystem>  // std::filesystem::rename
      #include <string_view> // std::string_view
      using namespace std::literals;
      
      int main()
      {
          const std::filesystem::path path{ "D:/...complete directory" };
          std::filesystem::rename(path / "foo.txt"sv, path / "bar.txt"sv);
      }
      

      如果我们需要在某些情况下或为特定扩展名重命名目录中的一组文件怎么办。那么,让我们将逻辑包装到一个类中。

      #include <filesystem>  // std::filesystem::rename
      #include <regex>       // std::regex_replace
      #include <iostream>
      #include <string>
      using namespace std::string_literals;
      namespace fs = std::filesystem;
      
      class FileRenamer /* final */
      {
      private:
          const fs::path mPath;
          const fs::path mExtension;
      
      private:
          template<typename LogicFunc>
          bool renameImpli(const LogicFunc& func, const fs::path& extension = {}) noexcept
          {
              bool result = true;
              const fs::path extToCheck = extension.empty() ? this->mExtension : extension;
      
              // iterate through all the files in the given directory
              for (const auto& dirEntry : fs::directory_iterator(mPath))
              {
                  if (fs::is_regular_file(dirEntry)  && dirEntry.path().extension() == extToCheck)
                  {
                      const std::string currentFileName = dirEntry.path().filename().string();
                      const std::string newFileName = std::invoke(func, currentFileName);
                      try
                      {
                          fs::rename(mPath / currentFileName, mPath / newFileName);
                      }
                      catch (fs::filesystem_error& error) // if the renaming was unsuccessful
                      {
                          std::cout << error.code() << "\n" << error.what() << "\n";
                          result = false; // at least one of the renaming was unsuccessful!
                      }
                  }
              }
              return result;
          }
      
      public:
          explicit FileRenamer(fs::path path, fs::path extension = { ".txt" }) noexcept
              : mPath{ std::move(path) }
              , mExtension{ std::move(extension) }
          {}
          // other constructors as per!
      
          bool findAndReplace(const std::string& findWhat, const std::string& replaceWith, const fs::path& extension = {})
          {
              const auto logic = [&](const std::string& currentFileName) noexcept {
                  return std::regex_replace(currentFileName, std::regex{ findWhat }, replaceWith);
              };
              return renameImpli(logic, extension);
          }
      
          bool renameAll(const std::string& fileName, fs::path extension = {})
          {
              auto index{ 1u };
              const auto logic = [&](const std::string&) noexcept { 
                  return std::to_string(index++) + " - "s + fileName + extension.string(); 
              };
              return renameImpli(logic, extension);
          }
      };
      
      int main()
      {
          FileRenamer fileRenamer{  "D:/"}; // ...complete directory
      
          /*! Rename the files in the given directory with specific extension (.txt by default)
           * in such a way that, filename contained the passed string (i.e. here "foo") will be
           * replaced to what mentioned (i.e. here "bar").
           * Ex:    foo.txt           -->  bar.txt
           *        pre_foo_post.txt  -->  File of bar.txt
           *        File of foo.txt   -->  pre_bar_post.txt
           */
          fileRenamer.findAndReplace("foo"s, "bar"s);
      
          /*! All the files in the given directory with specific extension (.txt by default)
           * will be replaced to specific filename provided, additional with an index.
           * Ex:    foo.txt           -->  1 - foo.txt
           *        pre_foo_post.txt  -->  2 - foo.txt
           *        File of foo.txt   -->  3 - foo.txt
           */
          fileRenamer.renameAll("foo", ".txt");
      }
      

      【讨论】:

        猜你喜欢
        • 2015-09-12
        • 2017-05-29
        • 2017-03-31
        • 1970-01-01
        • 2018-04-03
        • 2012-02-02
        • 2019-04-27
        • 2023-03-18
        • 1970-01-01
        相关资源
        最近更新 更多