如何在 C 语言中更改文本文件的名称?

发布于 2024-11-09 10:44:52 字数 121 浏览 0 评论 0原文

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

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

I would like to change a txt file's name, but I can not find how to do this.

For example, I want to rename foo.txt to boo.txt in my C++ program.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

像你 2024-11-16 10:44:52

#include(或)并使用rename(或std::rename):

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

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

#include <stdio.h> (or <cstdio>) and use rename (or std::rename):

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

Contrary to popular belief, this is included in the standard library, and is portable up to a point -- though of course the allowable contents of the strings will vary with the target system.

晨与橙与城 2024-11-16 10:44:52

C++17 的 更新!

多年后,我们有了
因此,另一篇文章和评论中提到的投诉“C++不直接支持文件系统”不再有效!

支持 ISO 或更高版本,现在我们可以使用 std::filesystem::重命名并执行以下操作:

#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");
}

C++17's <filesystem> Updates!

Years after now we have <filesystem> in C++ standard.
Therefore, the complaint mentioned in the other post and comments "C++ does not directly support file systems" is no longer valid!

The compiler which supports ISO or later, now we can use std::filesystem::rename and do as follows:

#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);
}

What if we need to rename a group of files in a directory under some conditions or for a specific extension. Let's wrap the logic into a class, then.

#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");
}
大海や 2024-11-16 10:44:52

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

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

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

  • 使用目标操作系统的 API

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

Boost::文件系统是这样的抽象出平台差异的 C++ 库。

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

Filesystem support is notably absent from the C++ standard library. As Jerry Coffin's answer shows, there actually is a rename function in stdio (contrary to the popular belief which I shared). There are however many filesystem-related appliances that the standard lib does not cover, hence the existence of Boost::Filesystem (notably manipulating directories and retrieving information about files).

This is a design decision to make C++ less constrained (i.e. make it possible to compile on a wide range of platforms including embedded systems where the idea of a file is non-existent).

To perform file operations, one has two options:

  • Use the API of the target OS

  • Use a library that provides a unified interface across platforms

Boost::Filesystem is such C++ library that abstracts away platform differences.

You can use the Boost::Filesystem::rename to rename a file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文