我的問題很簡單,但我無法到目前爲止找到一個解決方案:如何在C/C++中將字符串從UTF8轉換爲Latin1?
我如何轉換utf-8編碼string
到latin1的用C編碼string
++而不使用任何額外的庫像libiconv的?
到目前爲止我能找到的每個例子都是針對latin1到UTF8的轉換?
我的問題很簡單,但我無法到目前爲止找到一個解決方案:如何在C/C++中將字符串從UTF8轉換爲Latin1?
我如何轉換utf-8編碼string
到latin1的用C編碼string
++而不使用任何額外的庫像libiconv的?
到目前爲止我能找到的每個例子都是針對latin1到UTF8的轉換?
typedef unsigned value_type;
template <typename Iterator>
size_t get_length (Iterator p)
{
unsigned char c = static_cast<unsigned char> (*p);
if (c < 0x80) return 1;
else if (!(c & 0x20)) return 2;
else if (!(c & 0x10)) return 3;
else if (!(c & 0x08)) return 4;
else if (!(c & 0x04)) return 5;
else return 6;
}
template <typename Iterator>
value_type get_value (Iterator p)
{
size_t len = get_length (p);
if (len == 1)
return *p;
value_type res = static_cast<unsigned char> (
*p & (0xff >> (len + 1)))
<< ((len - 1) * 6);
for (--len; len; --len)
res |= (static_cast<unsigned char> (*(++p)) - 0x80) << ((len - 1) * 6);
return res;
}
該函數將返回位於p
的unicode代碼點。現在,您可以轉換爲使用
for (std::string::iterator p = s_utf8.begin(); p != s_utf8.end(); ++p)
{
value_type value = get_value<std::string::iterator&>(p));
if (value > 0xff)
throw "AAAAAH!";
s_latin1.append(static_cast<char>(value));
}
不能保證一個字符串,該代碼是很老:)
latin1
(又名ISO-8859-1
)定義了Unicode的前256個編碼點。因此,在UTF-8
中,如果您的字符是8位,那麼它將精確映射到latin1
等價物。如果長度超過8位,那麼在latin1
內沒有通訊者,您應該將其映射到某個「未知字符」(例如,\0
或?)。
這是不正確的。它只適用於* 7 *位。 – filmor
真的嗎?該死......在這種情況下,我猜測OP可以使用這個,然後手動映射剩下的128個點。 – Xophmeister
從UTF-16到latin1的轉換隻是簡單地刪除每一個零,但是從UTF-8到latin1的轉換有點複雜。 – Dialecticus
這裏是filmor的答案,我寫我的目的的一個版本。更可讀,可能會慢一點。我不需要模板的東西,因爲我總是處理char *
,在我的情況下,我想用_替換非Latin1字符。萬一它可以幫助別人:
int GetUtf8CharacterLength(unsigned char utf8Char)
{
if (utf8Char < 0x80) return 1;
else if ((utf8Char & 0x20) == 0) return 2;
else if ((utf8Char & 0x10) == 0) return 3;
else if ((utf8Char & 0x08) == 0) return 4;
else if ((utf8Char & 0x04) == 0) return 5;
return 6;
}
char Utf8ToLatin1Character(char *s, int *readIndex)
{
int len = GetUtf8CharacterLength(static_cast<unsigned char>(s[ *readIndex ]));
if (len == 1)
{
char c = s[ *readIndex ];
(*readIndex)++;
return c;
}
unsigned int v = (s[ *readIndex ] & (0xff >> (len + 1))) << ((len - 1) * 6);
(*readIndex)++;
for (len-- ; len > 0 ; len--)
{
v |= (static_cast<unsigned char>(s[ *readIndex ]) - 0x80) << ((len - 1) * 6);
(*readIndex)++;
}
return (v > 0xff) ? 0 : (char)v;
}
// overwrites s in place
char *Utf8ToLatin1String(char *s)
{
for (int readIndex = 0, writeIndex = 0 ; ; writeIndex++)
{
if (s[ readIndex ] == 0)
{
s[ writeIndex ] = 0;
break;
}
char c = Utf8ToLatin1Character(s, &readIndex);
if (c == 0)
{
c = '_';
}
s[ writeIndex ] = c;
}
return s;
}
測試代碼:
char s2[ 256 ] = "lif\xc3\xa9 is b\xc3\xa9tt\xc3\xa9r with acc\xc3\xa9nts";
Utf8ToLatin1String(s2);
UTF8可以代表65536個點; latin1(ISO-8859-1)只能表示256.你想如何處理所有無法轉換的字符? – simonc
你可以轉換成C這個http://www.jamesmurty.com/2011/12/30/python-code-utf8-to-latin1/(注意不是所有的符號都可以轉換) –
@DavidRF條件「不使用任何額外的庫「意味着不使用現成的函數,如在給定代碼的最後一行,'utf8_text.encode('ISO-8859-1','替換')' – Dialecticus