C++保存unicode命名的文件问题 - 如何以跨平台方式正确保存UTF-8文件名?

5
我想要保存一个名为Привет Мир.jpg的文件。我接收到一个包含Unicode的字符串(例如从文件中读取),但我的C++代码将其保存为ÐÑÐ¸Ð²ÐµÑ ÐиÑ.jpg。我该怎么做才能正确保存它?(顺便说一句,如果我只是将该字符串保存到文件中,它会正确保存,这意味着只有我保存文件名的方式有些错误。如何修复?)
以下是我的文件保存代码:
void file_service::save_string_into_file( std::string contents, std::string name )
{
    std::string pathToUsers = this->root_path.string() + "/users/";
    boost::filesystem::path users_path ( this->root_path / "users/" );
    users_directory_path = users_path;
    general_util->create_directory(users_directory_path);
    std::ofstream datFile;
    name = users_directory_path.string() + name;
    datFile.open(name.c_str(), std::ofstream::binary | std::ofstream::trunc | std::ofstream::out    );
    datFile.write(contents.c_str(), contents.length());
    datFile.close();
}

where

void general_utils::create_directory( boost::filesystem::path path )
{
    if (boost::filesystem::exists( path ))
    {
        return;
    }
    else
    {
        boost::system::error_code returnedError;
        boost::filesystem::create_directories( path, returnedError );
        if ( returnedError )
        {
            throw std::runtime_error("problem creating directory");
        }
    }
}

更新:在帮助下,我现在有了。
void file_service::save_string_into_file( std::string contents, std::string s_name )
{
    boost::filesystem::path users_path ( this->root_path / "users" );
    users_directory_path = users_path;
    general_util->create_directory(users_directory_path);
    boost::filesystem::ofstream datFile;
    boost::filesystem::path name (users_directory_path / s_name);
    datFile.open(name, std::ofstream::binary | std::ofstream::trunc | std::ofstream::out    );
    datFile.write(contents.c_str(), contents.length());
    datFile.close();
}

但是,当我保存文件时,它将其文件名保存为Привет РњРёСЂ.jpg,那么,现在我该怎么办?

你正在使用 std::string。你的字符串是否为 UTF-8 编码?你使用的是什么操作系统? - David Heffernan
目前我使用Win 7,但我还需要支持Linux和Mac OS X。 - Rella
首先,你需要处理的事实是Windows使用UTF-16编码,而*nix使用UTF-8编码。 - David Heffernan
字符串没有编码就不存在。s_name 是什么编码?如果你不知道,那么你就有问题了。 - Nicol Bolas
请将 request->body 编码为 UTF-8 字符串,因为它是从浏览器发送给我们的...希望如此。 - Rella
显示剩余2条评论
1个回答

5

C++标准库不支持Unicode。因此,您必须使用支持Unicode的库(例如Boost.Filesystem)。

或者,您需要处理特定于平台的问题。Windows支持UTF-16,因此如果您有UTF-8字符串,则需要将它们转换为UTF-16(std::wstring)。然后将其作为文件名传递给iostream文件打开函数。Visual Studio版本的文件流可以接受wchar_t*作为文件名。


2
那么如何通过Boost.Filesystem保存文件以获得正确的文件名呢? - Rella
你可以使用Boost.Filesystem中使用的file streams之一。或者,你可以从path对象中获取本地字符串(在Windows上将是std::wstring,在其他地方将是std::string),并将其提供给std::ifstream - Nicol Bolas
1
嗯...你的方法能否集成到我的save_string_into_file函数中? - Rella
1
你可以根据我给你的链接,将 std::ofstream 替换为 boost::filesystem::ofstream。然后直接使用 boost::path,而不是将其转换为 std::string - Nicol Bolas

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