標籤:libiconv big5 gbk
《libiconv字元集轉換庫使用方法》一文中說到了libiconv可以實現不同字元集的轉換。比如GBK轉BIG5等。在項目中因為需要,找到這個庫。可是這個庫在C#中沒有很好的支援。不過,想著既然是C++的庫,那隻要動態載入DLL的介面就好了。可是調用並不順利,傳進去的IntPtr或者byte數組總是拿不到資料。後面回到了C++的方式去調用,幾經調試,總算找到了原因。
是iconv介面在轉換完成後,指標的位置往後移了。而在C#中調用DLL後回來的指標,已經是移動後的,所以拿不到所要的資料。
經過多種嘗試,沒有辦法將指標移回到原位。
後來,通過C++的二次封裝,在C++中將指標的位置移到了原來的位置,再用C#來調用,總算達到了目的。
#include <fstream>//包函 libiconv庫標頭檔 #include "iconv.h"//匯入 libiconv庫 #pragma comment(lib,"libiconv.lib")using namespace std;#define DLL_EXPORT extern "C" __declspec(dllexport)DLL_EXPORT int ChangeCode( const char* pFromCode, const char* pToCode, const char* pInBuf, size_t* iInLen, char* pOutBuf, size_t* iOutLen ){ size_t outLenTemp=*iOutLen;iconv_t hIconv = iconv_open( pToCode, pFromCode );if ( -1 == (int)hIconv ){return -100;//開啟失敗,可能不支援的字元集 }//開始轉換 int iRet = iconv( hIconv, (const char**)(&pInBuf), iInLen, (char**)(&pOutBuf), iOutLen );if (iRet>=0){pOutBuf=pOutBuf-(outLenTemp-*iOutLen);//轉換後pOutBuf的指標被移動,必須移回到起始位置}else{iRet=-200;}//關閉字元集轉換 iconv_close( hIconv );return iRet;}
C#調用的部分
/// <summary> /// 字元器轉換. /// 每次轉換都需要開啟轉換器、字元集轉換、關閉轉換器。 /// </summary> /// <param name="pFromCode">源字元集編碼</param> /// <param name="pToCode">目標字元集編碼</param> /// <param name="pInBuf">待轉換的內容</param> /// <param name="iInLen">待轉換的長度。轉換成功後,將變成0.</param> /// <param name="pOutBuf">轉換後的內容</param> /// <param name="iOutLen">轉換長度。轉換成功後,將變成原值減去轉換後的內容所佔空間的長度</param> /// <returns></returns> [DllImport("CharsetConvert.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int ChangeCode(string pFromCode, string pToCode, byte[] pInBuf, ref int iInLen, byte[] pOutBuf, ref int iOutLen);
private void buttonOneConvert_Click(object sender, EventArgs e) { string toCode = "BIG5"; string fromCode = "GBK"; string inStr = "國k"; byte[] inBuf = Encoding.Default.GetBytes(inStr); byte[] outBuf = new byte[100]; int inLen = inBuf.Length; int outLen = outBuf.Length; int result = CharsetConvter.ChangeCode(fromCode, toCode, inBuf, ref inLen, outBuf, ref outLen); if (result < 0) { MessageBox.Show("轉換失敗"); } else { String outStr = Encoding.GetEncoding("BIG5").GetString(outBuf); MessageBox.Show(outStr); } }