MrErfan
MrErfan

Reputation: 81

c++ renaming filename other language

I want to rename some of the files ,

The names of some of the files are Russian, Chinese, and German

The program can only modify files whose name is English.

What is the problem ? please guide me

std::wstring ToUtf16(std::string str)
{
    std::wstring ret;
    int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
    if (len > 0)
    {
        ret.resize(len);
        MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &ret[0], len);
    }
    return ret;
}
int main()
{
    const std::filesystem::directory_options options = (
        std::filesystem::directory_options::follow_directory_symlink |
        std::filesystem::directory_options::skip_permission_denied
        );
    try
    {
        for (const auto& dirEntry :
            std::filesystem::recursive_directory_iterator("C:\\folder",
                std::filesystem::directory_options(options)))
        {
            filesystem::path  myfile(dirEntry.path().u8string());
            string uft8path1 = dirEntry.path().u8string();
            string uft8path3 = myfile.parent_path().u8string() + "/" + myfile.filename().u8string();
            _wrename(
                ToUtf16(uft8path1).c_str()
                ,
                ToUtf16(uft8path3).c_str()
            );
            std::cout << dirEntry.path().u8string() << std::endl;
        }
    }
    catch (std::filesystem::filesystem_error & fse)
    {
        std::cout << fse.what() << std::endl;
    }
    system("pause");
}

enter image description here

Upvotes: 0

Views: 278

Answers (1)

Barmak Shemirani
Barmak Shemirani

Reputation: 31599

filesystem::path  myfile(dirEntry.path().u8string());

Windows supports UTF16 and ANSI, there is no UTF8 support for APIs (not standard anyway). When you supply UTF8 string, it thinks there is ANSI input. Use wstring() to indicate UTF16:

filesystem::path  myfile(dirEntry.path().wstring());

or just put:

filesystem::path  myfile(dirEntry);

Likewise, use wstring() for other objects.

wstring path1 = dirEntry.path();
wstring path3 = myfile.parent_path().wstring() + L"/" + myfile.filename().wstring();
_wrename(path1.c_str(), path3.c_str());

Renaming the files will work fine when you have UTF16 input. But there is another problem with console's limited Unicode support. You can't print some Asian characters with font changes. Use the debugger or MessageBoxW to view Asian characters.

Use _setmode and wcout to print UTF16.

Also note, std::filesystem supports / operator for adding path. Example:

#include <io.h> //for _setmode
#include <fcntl.h> 
...

int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);

    const std::filesystem::directory_options options = (
        std::filesystem::directory_options::follow_directory_symlink |
        std::filesystem::directory_options::skip_permission_denied
        );
    try
    {
        for(const auto& dirEntry :
            std::filesystem::recursive_directory_iterator(L"C:\\folder",
                std::filesystem::directory_options(options)))
        {
            filesystem::path  myfile(dirEntry);
            auto path1 = dirEntry;
            auto path3 = myfile.parent_path() / myfile;
            std::wcout << path1 << ", " << path3 << endl;
            //filesystem::rename(path1, path3);
        }
    }
    ...
}

Upvotes: 1

Related Questions