(1) 從字串轉為固定大小的字元數組
如:定義固定大小的結構體:
(使用命名空間:using System.Runtime.InteropServices;)
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] struct OnlineUsrInfo { [MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] public char[] name; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public char[] IP; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public char[] port; }
將string轉為char[]時,需要用string對象的PadRight()方法來填充一定大小的字元數組
OnlineUsrInfo.name=str.PadRight(16);
這個方法有一個弊端,就是在name中,記憶體部分內容為空白格,如果傳遞給C++程式使用,會因為沒有字串終結符“\0”而一直把結構體中的字元讀完,從而導致出錯
故,一般用PadRight()方法的重載函數 PadRight(16, '\0'); 來實現
注意:最好用PadRight(int nWidth, '\0'); 來填充,否則會預設以空格(space=32)來填充;
(2)從字元數組轉為字串時的問題
同樣,從C++端傳過來的字元數組,會記憶體初始化為0,即‘\0’
如接收到的字元數組內容為:"xuwei\0\0\0\0\0\0\0\0\0\0\0"
將該字元數組轉為字串時,會將之後的'\0'都算到字串內
因此,如何把字串中的 '\0' 去掉也是一個問題
想到的方法有兩個:
(一)用string對象的Trim()方法,即Trim('\0'),去掉所有的'\0'字元
(二)用string對象的Replace()方法,即Replace('\0', ''),用空格去代替‘\0’ 字串會自動過濾掉空格
(3) 關於結束符的問題
C# 字串末尾沒有以 null('0')結尾的字元;而在C++中,字串末尾以null('\0')結束
因此,在傳輸時,要注意字串的處理
1> 從C#端傳輸到C++端:
例如,發送"hello",5個char
由於C++端不知道結束符,所以可能收到"hello]"之類的錯誤;即會有亂碼
因此,在C++端接收時,應該將收到的字元再處理一下;
2> 從C++端傳輸到C#端
例如,發送"hello",5個char(佔5Byte)
如果只是發送5個位元組,則接收端可能會收到104 101 108 108 108,即"helll";
如果發送6個位元組,接收端以為接收到6個char,最後可能會收到104 101 108
108 111 111,即"helloo";(最後一個為亂碼)
因此,最後選擇的辦法是:發送6byte,但通知接收端只有5個char
(4)不同平台的編碼方式的轉換
C#端使用的是utf-16編碼方式;Linux中C++使用的是utf-8編碼方式;Windows中C++使用的是ANSI編碼方式;
因此,在轉換的時候要轉換成通用的編碼,如utf-16
Linux中可以用iconv()函數族進行utf-8->utf-16的編碼轉換;
Windows中可以用mbstowcs()/MultiByteToWideChar()等函數來進行ANSI->utf-16的編碼轉換
(5)關於中文的轉換
英文的話,一個utf-16碼(一個char)轉換為一個utf-8碼(一個char);
但中文的話,一個utf-16(一個char)轉換成了三個utf-8碼(三個char);
因此,C#發送中文給C++發送中文時,需要告訴用戶端需要處理多少char
C#端可通過UnicodeEncoding.UTF8.GetByteCount(data); 來擷取data轉換成utf-8之後的char個數,以便接收端進行處理
補充的幾個知識點:
1> C#可用Encoding.Default.EncodingName來輸出預設的編碼名