如何将UTF-8string转换为Unicode?

我有显示UTF-8编码字符的string,我想将其转换回Unicode。

现在,我的实现如下:

public static string DecodeFromUtf8(this string utf8String) { // read the string as UTF-8 bytes. byte[] encodedBytes = Encoding.UTF8.GetBytes(utf8String); // convert them into unicode bytes. byte[] unicodeBytes = Encoding.Convert(Encoding.UTF8, Encoding.Unicode, encodedBytes); // builds the converted string. return Encoding.Unicode.GetString(encodedBytes); } 

我正在玩"déjà"这个词。 我已经通过这个在线工具将它转换为UTF-8,于是我开始用string"déjÃ"来testing我的方法。

不幸的是,在这个实现中,string保持不变。

我错在哪里?

所以问题在于,UTF-8代码单元值已经被存储为一个C# string的16位代码单元string 。 您只需validation每个代码单元是否在一个字节范围内,将这些值复制到字节中,然后将新的UTF-8字节序列转换为UTF-16。

 public static string DecodeFromUtf8(this string utf8String) { // copy the string as UTF-8 bytes. byte[] utf8Bytes = new byte[utf8String.Length]; for (int i=0;i<utf8String.Length;++i) { //Debug.Assert( 0 <= utf8String[i] && utf8String[i] <= 255, "the char must be in byte's range"); utf8Bytes[i] = (byte)utf8String[i]; } return Encoding.UTF8.GetString(utf8Bytes,0,utf8Bytes.Length); } DecodeFromUtf8("d\u00C3\u00A9j\u00C3\u00A0"); // déjà 

这很容易,但最好find根本原因; 某人将UTF-8代码单元复制到16位代码单元的位置。 可能的罪魁祸首是某人使用错误的编码将字节转换为C# string 。 例如Encoding.Default.GetString(utf8Bytes, 0, utf8Bytes.Length)


或者,如果您确定知道用于生成string的不正确的编码,并且不正确的编码转换是无损的(通常情况下,如果不正确的编码是单字节编码),那么您可以简单地进行逆编码步骤来获得原始的UTF-8数据,然后你可以做UTF-8字节的正确转换:

 public static string UndoEncodingMistake(string mangledString, Encoding mistake, Encoding correction) { // the inverse of `mistake.GetString(originalBytes);` byte[] originalBytes = mistake.GetBytes(mangledString); return correction.GetString(originalBytes); } UndoEncodingMistake("d\u00C3\u00A9j\u00C3\u00A0", Encoding(1252), Encoding.UTF8); 

如果你有一个UTF-8string,每个字节都是正确的('Ö' – > [195,0],[150,0]),你可以使用下面的代码:

 public static string Utf8ToUtf16(string utf8String) { /*************************************************************** * Every .NET string will store text with the UTF-16 encoding, * * known as Encoding.Unicode. Other encodings may exist as * * Byte-Array or incorrectly stored with the UTF-16 encoding. * * * * UTF-8 = 1 bytes per char * * ["100" for the ansi 'd'] * * ["206" and "186" for the russian '?'] * * * * UTF-16 = 2 bytes per char * * ["100, 0" for the ansi 'd'] * * ["186, 3" for the russian '?'] * * * * UTF-8 inside UTF-16 * * ["100, 0" for the ansi 'd'] * * ["206, 0" and "186, 0" for the russian '?'] * * * * First we need to get the UTF-8 Byte-Array and remove all * * 0 byte (binary 0) while doing so. * * * * Binary 0 means end of string on UTF-8 encoding while on * * UTF-16 one binary 0 does not end the string. Only if there * * are 2 binary 0, than the UTF-16 encoding will end the * * string. Because of .NET we don't have to handle this. * * * * After removing binary 0 and receiving the Byte-Array, we * * can use the UTF-8 encoding to string method now to get a * * UTF-16 string. * * * ***************************************************************/ // Get UTF-8 bytes and remove binary 0 bytes (filler) List<byte> utf8Bytes = new List<byte>(utf8String.Length); foreach (byte utf8Byte in utf8String) { // Remove binary 0 bytes (filler) if (utf8Byte > 0) { utf8Bytes.Add(utf8Byte); } } // Convert UTF-8 bytes to UTF-16 string return Encoding.UTF8.GetString(utf8Bytes.ToArray()); } 

在我的情况下,DLL的结果也是一个UTF-8string,但不幸的是,UTF-8string是用UTF-16编码('Ö' – > [195,0],[19,32])解释的。 因此,150的ANSI' – '被转换为UTF-16' – '这是8211.如果你也有这种情况,你可以使用下面的代码:

 public static string Utf8ToUtf16(string utf8String) { // Get UTF-8 bytes by reading each byte with ANSI encoding byte[] utf8Bytes = Encoding.Default.GetBytes(utf8String); // Convert UTF-8 bytes to UTF-16 bytes byte[] utf16Bytes = Encoding.Convert(Encoding.UTF8, Encoding.Unicode, utf8Bytes); // Return UTF-16 bytes as UTF-16 string return Encoding.Unicode.GetString(utf16Bytes); } 

或本机方法:

 [DllImport("kernel32.dll")] private static extern Int32 MultiByteToWideChar(UInt32 CodePage, UInt32 dwFlags, [MarshalAs(UnmanagedType.LPStr)] String lpMultiByteStr, Int32 cbMultiByte, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder lpWideCharStr, Int32 cchWideChar); public static string Utf8ToUtf16(string utf8String) { Int32 iNewDataLen = MultiByteToWideChar(Convert.ToUInt32(Encoding.UTF8.CodePage), 0, utf8String, -1, null, 0); if (iNewDataLen > 1) { StringBuilder utf16String = new StringBuilder(iNewDataLen); MultiByteToWideChar(Convert.ToUInt32(Encoding.UTF8.CodePage), 0, utf8String, -1, utf16String, utf16String.Capacity); return utf16String.ToString(); } else { return String.Empty; } } 

如果您需要,请参阅Utf16ToUtf8 。 希望我能帮上忙。

我有显示UTF-8编码字符的string

.NET中没有这样的东西。 string类只能以UTF-16编码存储string。 一个UTF-8编码的string只能以byte []的forms存在。 试图将字节存储到一个string中不会有好结果; UTF-8使用没有有效的Unicode代码点的字节值。 当string被标准化时,内容将被销毁。 因此DecodeFromUtf8()开始运行时恢复string已经太迟了。

仅处理字节[]的UTF-8编码文本。 并使用UTF8Encoding.GetString()来转换它。

你似乎是从另一个编码错误解码的string ,可能是代码页1252 ,这是美国Windows默认。 假设没有其他损失,这是如何扭转的。 一个不是直接显而易见的损失就是不显示string末尾的non-breaking space (U + 00A0)。 当然,最好是正确地读取数据源,但可能数据源存储不正确。

 using System; using System.Text; class Program { static void Main(string[] args) { string junk = "déjÃ\xa0"; // Bad Unicode string // Turn string back to bytes using the original, incorrect encoding. byte[] bytes = Encoding.GetEncoding(1252).GetBytes(junk); // Use the correct encoding this time to convert back to a string. string good = Encoding.UTF8.GetString(bytes); Console.WriteLine(good); } } 

结果:

 déjà