簡體   English   中英

在Linux中將std :: string轉換為Unicode

[英]Convert std::string to Unicode in Linux

編輯我在意識到開始之后是錯誤的時候修改了這個問題。

我正在將一部分C#應用程序移植到Linux,我需要獲取UTF-16字符串的字節:

string myString = "ABC";
byte[] bytes = Encoding.Unicode.GetBytes(myString);

這樣bytes數組現在是:

"65 00 66 00 67 00" (bytes)

如何在Linux上用C ++實現相同的功能呢? 我有一個myString定義為std::string ,似乎Linux上的std::wstring是4個字節?

你的問題不是很清楚,但我會試着澄清一些困惑。

介紹

在'95修訂C標准之后,在C中處理字符集(以及由C ++繼承)的狀態。

  • 使用的字符集由當前語言環境給出

  • wchar_t用於存儲代碼點

  • char用於存儲多字節編碼形式(例如,約束是基本字符集中的字符必須以一個字節編碼)

  • 字符串文字以實現定義的方式編碼。 如果它們使用基本字符集之外的字符,則不能假定它們在所有語言環境中都有效。

因此,使用16位wchar_t您只能使用BMP。 使用UTF-16的代理是不合規的,但我認為MS和IBM或多或少被迫這樣做,因為他們認為Unicode時他們永遠是一個16位字符集。 那些延遲了他們的Unicode支持的人傾向於使用32位wchar_t。

較新的標准變化不大。 主要有UTF-8,UTF-16和UTF-32編碼字符串的文字,有16位和32位字符的類型。 標准庫中很少或沒有對Unicode的額外支持。

如何將一種編碼轉換為另一種編碼

您必須處於使用Unicode的語言環境中。 希望

std::locale::global(locale(""));

就足夠了。 如果沒有,您的環境沒有正確設置(或設置為另一個字符集,並假設Unicode不是您的用戶的服務。)。

C風格

使用wcstomsbmbstowcs功能。 這是你問的例子。

std::string narrow(std::wstring const& s)
{
    std::vector<char> result(4*s.size() + 1);
    size_t used = wcstomsb(&result[0], s.data(), result.size());
    assert(used < result.size());
    return result.data();
}

C ++風格

語言環境的codecvt方面提供了所需的功能。 優點是您不必更改使用它的全局語言環境。 不方便的是使用更復雜。

#include <locale>
#include <iostream>
#include <string>
#include <vector>
#include <assert.h>
#include <iomanip>

std::string narrow(std::wstring const& s,
                   std::locale loc = std::locale())
{
    std::vector<char> result(4*s.size() + 1);
    wchar_t const* fromNext;
    char* toNext;
    mbstate_t state = {0};
    std::codecvt_base::result convResult
        = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(loc)
        .out(state,&s[0], &s[s.size()], fromNext,
             &result[0], &result[result.size()], toNext);

    assert(fromNext == &s[s.size()]);
    assert(toNext != &result[result.size()]);
    assert(convResult == std::codecvt_base::ok);
    *toNext = '\0';

    return &result[0];
}

std::wstring widen(std::string const& s,
                   std::locale loc = std::locale())
{
    std::vector<wchar_t> result(s.size() + 1);
    char const* fromNext;
    wchar_t* toNext;
    mbstate_t state = {0};
    std::codecvt_base::result convResult
        = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t> >(loc)
        .in(state, &s[0], &s[s.size()], fromNext,
            &result[0], &result[result.size()], toNext);

    assert(fromNext == &s[s.size()]);
    assert(toNext != &result[result.size()]);
    assert(convResult == std::codecvt_base::ok);
    *toNext = L'\0';

    return &result[0];
}

你應該通過更好的處理來替換斷言。

順便說一句,這是標准的C ++,並且不假設Unicode除了計算結果大小之外,你可以通過檢查convResult來做得更好,這可以指示部分轉換)。

最簡單的方法是獲取一個小型庫,例如UTF8 CPP,並執行以下操作:

utf8::utf8to16(line.begin(), line.end(), back_inserter(utf16line));

我通常使用Poco C ++庫中的UnicodeConverter類。 如果您不想要依賴關系,那么您可以查看代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM