宽字符窄字符的相互转化

本文介绍了如何在C++中处理含有中文路径的文件,通过将宽字符路径(std::wstring)转换为窄字符(std::string)来解决因宽字符编码导致的ReadFile函数读取失败问题,利用std::wstring_convert和std::codecvt_utf8实现编码转换。
摘要由CSDN通过智能技术生成

宽字符窄字符的转化

问题

当step文件的存放路径有中文时,会导致读取失败。

宽、窄字符

在C和C++中,宽字符(wide characters)和窄字符(narrow characters)是用来表示字符的不同方式。

宽字符(wide characters)

  • 宽字符通常使用多个字节来表示一个字符,通常采用 Unicode 编码方式,比如 UTF-16 或 UTF-32。
  • 在C和C++中,宽字符类型通常是 wchar_t 类型,用于表示宽字符。
  • 宽字符用于处理各种语言中的特殊字符、符号以及其他语言特定的文本处理需求,因为 Unicode 编码支持了几乎所有的语言字符。

窄字符(narrow characters)

  • 窄字符是使用单个字节来表示一个字符,通常采用 ASCII 或其他类似的编码方式。
  • 在C和C++中,窄字符类型通常是 char 类型。
  • 窄字符通常用于处理英文、数字和一些基本的符号,它们可以直接在单字节字符编码中表示。

因为我们使用string来存放字符串,因此当路径字符串中有中文时,我们需要将其转换为宽字符(wstring)然后再转换为窄字符(string)。

通过将 string 类型的路径转换为 wstring 类型,然后再转换回 string 类型,可以避免在窄字符编码下的限制。即使最终路径是 string 类型,但由于在转换过程中使用了宽字符编码,因此能够正确处理中文字符,从而使 ReadFile 函数能够读取到正确的路径并成功打开文件。

std::wstring StringToWstring::StoWs(std::string str)
{
    const char* sBuf = str.c_str();

    //获取输入缓存大小
    int sBufSize = static_cast<int>(str.size()) + 1; // 包括终止符
    //获取输出缓存大小
    //VC++ 默认使用ANSI,故取第一个参数为CP_ACP
    DWORD dBufSize = MultiByteToWideChar(CP_ACP, 0, sBuf, sBufSize, NULL, 0);
    printf("需要wchar_t%u个\n", dBufSize);

    wchar_t* dBuf = new wchar_t[dBufSize];
    wmemset(dBuf, 0, dBufSize);

    //进行转换
    int nRet = MultiByteToWideChar(CP_ACP, 0, sBuf, sBufSize, dBuf, dBufSize);

    if (nRet <= 0)
    {
        std::cout << "转换失败" << std::endl;
        DWORD dwErr = GetLastError();
        switch (dwErr)
        {
        case ERROR_INSUFFICIENT_BUFFER:
            printf("ERROR_INSUFFICIENT_BUFFER\n");
            break;
        case ERROR_INVALID_FLAGS:
            printf("ERROR_INVALID_FLAGS\n");
            break;
        case ERROR_INVALID_PARAMETER:
            printf("ERROR_INVALID_PARAMETER\n");
            break;
        case ERROR_NO_UNICODE_TRANSLATION:
            printf("ERROR_NO_UNICODE_TRANSLATION\n");
            break;
        }
    }
    else
    {
        std::cout << "转换成功" << std::endl;
        std::cout << dBuf;
    }
   
    return dBuf;
}
void stpRead(std::string& stp_location, TopoDS_Shape& shape)
{
    StringToWstring ws;
    
    std::wstring wideStr1 = ws.StoWs(stp_location);

    //宽字符保存中文路径
    std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
    //将宽字符路径转换为窄字符路径
    std::string narrowFilePath = converter.to_bytes(wideStr1);

    STEPControl_Reader reader;
    IFSelect_ReturnStatus status = reader.ReadFile(narrowFilePath.c_str());
    // 检查读取状态
    if (status != IFSelect_RetDone) {
        std::cout << "无法读取文件" << std::endl;
    }

    // 转化为 TopoDS_Shape 存储
    if (reader.TransferRoots()) { // 转化为OCC结构存入reader中
        shape = reader.OneShape();
    }
    else
    {
        std::cout << "step读取实体失败!" << std::endl;
    }
}

这段代码使用了 std::wstring_convertstd::codecvt_utf8 类来进行宽字符(std::wstring)到窄字符(std::string)的转换,主要用于将宽字符路径转换为窄字符路径。

  1. std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;:
    • 这一行创建了一个 std::wstring_convert 对象,指定了使用 std::codecvt_utf8<wchar_t> 类型的转换器。这个转换器用于将宽字符(wchar_t)编码的字符串转换为 UTF-8 编码的窄字符(char)编码的字符串。
  2. std::string narrowFilePath = converter.to_bytes(wideStr1);:
    • 这一行调用了 to_bytes 方法,将 std::wstring 类型的 wideStr1 转换为 std::string 类型的 narrowFilePath
    • to_bytes 方法接受一个 std::wstring 类型的参数,并将其转换为窄字符编码,通常是 UTF-8 编码,最终返回一个 std::string 类型的结果。
      rowFilePath`。
    • to_bytes 方法接受一个 std::wstring 类型的参数,并将其转换为窄字符编码,通常是 UTF-8 编码,最终返回一个 std::string 类型的结果。
    • 因为 ReadFile 函数需要接受窄字符路径(即 const char* 类型),所以这一步是必要的,以便将宽字符路径转换为窄字符路径,以便后续的文件读取操作。
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要将QString转换为字符(wchar_t*),可以按照以下步骤进行操作: 1. 将QString转换为std::string: QString提供了.toStdString()函数,可以将QString转换为std::string类型。 2. 将std::string转换为std::wstring: 首先,我们需要用std::wstring来存储转换后的字符。我们可以通过初始化一个具有与std::string相同长度的std::wstring,并将std::string复制到std::wstring中来实现。 可以使用std::wstring wstr(str.length(), L' ')来初始化字符std::wstring,并使用std::copy(str.begin(), str.end(), wstr.begin())将std::string复制到std::wstring中。 3. 将std::wstring转换为字符指针(wchar_t*): 最后,我们需要将std::wstring转换为字符指针(wchar_t*)。可以使用wstr.c_str()来获取字符指针。 综上所述,将QString转换为字符的代码示例如下: ``` QFileInfo info("./records.db"); std::string str = info.absoluteFilePath().toStdString(); //将QString转换为std::string std::wstring wstr(str.length(), L' '); //初始化字符std::wstring std::copy(str.begin(), str.end(), wstr.begin()); //将std::string复制到std::wstring const wchar_t* path = wstr.c_str(); //将std::wstring转换为字符指针 ``` 这样,你就可以将QString成功转换为字符了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [QString::toWCharArray可以拷贝到字符串里](https://blog.csdn.net/lengyuezuixue/article/details/80712817)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [863568206#guang.github.io#2019-7-26-QString与C++字符串类型的相互转换1](https://download.csdn.net/download/weixin_35819216/86257912)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [在QT中QString转char*避免中文乱码的问题](https://blog.csdn.net/xxwlf12138/article/details/124397355)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值