2012-05-27 54 views
5

我創建了將原生utf-8字符串(char *)轉換爲託管字符串的兩種方法,反之亦然。下面的代碼做這項工作:.net中的轉換:原生Utf-8 <->託管字符串

public IntPtr NativeUtf8FromString(string managedString) 
{ 
    byte[] buffer = Encoding.UTF8.GetBytes(managedString); // not null terminated 
    Array.Resize(ref buffer, buffer.Length + 1); 
    buffer[buffer.Length - 1] = 0; // terminating 0 
    IntPtr nativeUtf8 = Marshal.AllocHGlobal(buffer.Length); 
    Marshal.Copy(buffer, 0, nativeUtf8, buffer.Length); 
    return nativeUtf8; 
} 

string StringFromNativeUtf8(IntPtr nativeUtf8) 
{ 
    int size = 0; 
    byte[] buffer = {}; 
    do 
    { 
     ++size; 
     Array.Resize(ref buffer, size); 
     Marshal.Copy(nativeUtf8, buffer, 0, size); 
    } while (buffer[size - 1] != 0); // till 0 termination found 

    if (1 == size) 
    { 
     return ""; // empty string 
    } 

    Array.Resize(ref buffer, size - 1); // remove terminating 0 
    return Encoding.UTF8.GetString(buffer); 
} 

雖然NativeUtf8FromString是好的,StringFromNativeUtf8一片混亂,但唯一的安全碼我能得到執行。使用不安全的代碼我可以使用一個字節*,但我不想要不安全的代碼。有沒有另一種方法可以讓人想到我不必爲每個包含的字節複製字符串來找到0終止。


我只是添加了取消保存代碼在這裏:

public unsafe string StringFromNativeUtf8(IntPtr nativeUtf8) 
{ 
    byte* bytes = (byte*)nativeUtf8.ToPointer(); 
    int size = 0; 
    while (bytes[size] != 0) 
    { 
     ++size; 
    } 
    byte[] buffer = new byte[size]; 
    Marshal.Copy((IntPtr)nativeUtf8, buffer, 0, size); 
    return Encoding.UTF8.GetString(buffer); 
} 

正如你看到它不醜只是需要不安全。

+1

你爲什麼不在意使用'unsafe'代碼? – CodesInChaos

+0

@CodelnChaos:不確定。因爲Procect必須激活對我來說感覺髒的/不安全的開關。 – Totonga

+1

'/ unsafe'開關是相當無意義的。即使不需要開關,Marshal。*也與指針代碼一樣不安全。 – CodesInChaos

回答

19

只需執行strlen()執行完全相同的操作即可。請考慮保持緩衝區左右,代碼確實會匆忙產生垃圾。

public static IntPtr NativeUtf8FromString(string managedString) { 
     int len = Encoding.UTF8.GetByteCount(managedString); 
     byte[] buffer = new byte[len + 1]; 
     Encoding.UTF8.GetBytes(managedString, 0, managedString.Length, buffer, 0); 
     IntPtr nativeUtf8 = Marshal.AllocHGlobal(buffer.Length); 
     Marshal.Copy(buffer, 0, nativeUtf8, buffer.Length); 
     return nativeUtf8; 
    } 

    public static string StringFromNativeUtf8(IntPtr nativeUtf8) { 
     int len = 0; 
     while (Marshal.ReadByte(nativeUtf8, len) != 0) ++len; 
     byte[] buffer = new byte[len]; 
     Marshal.Copy(nativeUtf8, buffer, 0, buffer.Length); 
     return Encoding.UTF8.GetString(buffer); 
    } 
+0

byte [] buffer = new byte [len - 1]; 應該是 byte [] buffer = new byte [len]; – Jaska

+0

但是,您的代碼包含len到(但不包括)爲空終止符。所以len包含了沒有空終止符的字符數量。 – Jaska

+0

我可以發誓我測試了這個。一個錯誤吸吮。謝謝。 –

相關問題