以下方式 總歸 還是在使用使用java的string:"java/lang/String"
治根的辦法 還是完整地在native code 中實現。推薦可以使用開原始碼icu 或者iconv
android本身也是用了開源的庫: iconv,只預設是未對外匯出。
先放段代碼作為開頭,本段主要調用java中到建構函式,本段代碼實現,字串字元集轉換。
jstringMyNewString(JNIEnv *env, const char *chars, jint len){jclass stringClass;jmethodID cid;jbyteArray elemArr;jstring result;jstring jencoding;stringClass = env->FindClass("java/lang/String");if (stringClass == NULL) {return NULL; /* exception thrown */}/* Get the method ID for the String(byte[] data, String charsetName) constructor */cid = env->GetMethodID(stringClass,"<init>", "([BLjava/lang/String;)V");if (cid == NULL) {return NULL; /* exception thrown */}jencoding = env->NewStringUTF("GBK");/* Create a byte[] that holds the string characters */elemArr = env->NewByteArray(len);if (elemArr == NULL) {return NULL; /* exception thrown */}env->SetByteArrayRegion(elemArr, 0, len, (jbyte*)chars);/* Construct a java.lang.String object */result = (jstring)(env->NewObject(stringClass, cid, elemArr, jencoding));/* Free local references */env->DeleteLocalRef(elemArr);env->DeleteLocalRef(stringClass);return result;}
以上代碼時是參照《The JavaTM Native Interface Programmer’s Guide and Specification》改的。
這裡將字元集轉換的全部代碼貼上,記下以備忘,此外如果對大家有協助,那就更好了。
說穿了,其實就是在調用java.lang.String的方法。
一、CharToJString。
二、JStringToChar。
Mark:
以下代碼在轉中英文混合的字串時會出錯,原因是參數中的char*。更合適的介面可能應該如下:
jstring CharToJString(JNIEnv* env, const void* pszSrc, int nLen, const char* pszEncoding);int JStringToChar(JNIEnv* env, jstring jstr, const char *pszEncoding, void* pszOutBuf, int nBufLen);
java/native調用會比java/java調用慢上2~3倍,而雖然native/java調用,理論上和java/native效率一樣,可是,實際上,由於後者的使用比前者多得多,所以java/native可能得到了足夠多最佳化,這樣,native/java調用可能比java/native調用慢上10倍之多。
/* * you can use these function freely, but please keep this declaration with no modified. * * created by jerry.lin, 2011-08-04 */#include <stdio.h>#include <jni.h>#include <string.h>/* * convert the char string to JString * parameter: *[in]pszSrc: the source string to be converted. *[in]pszEncoding: the encoding of pszSrc, if it is null, means utf8 * * return value: * return the convered string if is successful, otherwise return NULL. */jstring CharToJString(JNIEnv* env, const char* pszSrc, const char* pszEncoding){jstring jstr = NULL;jclass stringClass = NULL;jbyteArray byteElemArr = NULL;do{jmethodID cid = NULL;jstring jstrEncoding = NULL;const char* pszEnco = NULL;int nStrLen = 0;/* check the income parameters */if (NULL == pszSrc || NULL == env){break;}/* get the String class of java and its constructor to create a new object *//* get the String class of java */stringClass = env->FindClass("java/lang/String");if (NULL == stringClass){break;}/* Get the method ID for the java.lang.String constructor */cid = env->GetMethodID(stringClass, "<init>", "([BLjava/lang/String;)V");if (NULL == cid){break;}if(NULL == pszEncoding){pszEnco = "utf-8";}else{pszEnco = pszEncoding;}jstrEncoding = env->NewStringUTF(pszEnco);if (NULL == jstrEncoding){break;}/* put char string into array of java */nStrLen = (int)strlen(pszSrc);byteElemArr = env->NewByteArray(nStrLen);if (NULL == byteElemArr){break;}env->SetByteArrayRegion(byteElemArr, 0, nStrLen, (jbyte*)pszSrc);/* create an new 0object of java.lang.String with the constructor string(byte[], string) */jstr = (jstring)(env->NewObject(stringClass, cid, byteElemArr, jstrEncoding));}while(0);/* Free local references */if (NULL != byteElemArr){env->DeleteLocalRef(byteElemArr);}if (NULL != stringClass){env->DeleteLocalRef(stringClass);}return jstr;}/* * convert the JString to char string. * * parameter: * [in]jstr: the source string to be converted. * [in]pszEncoding: the encoding to which the JString to be converted. * [out]pszOutBuf: the buffer to remain the changed string. * [in] nBufLen: the length of the buffer. * * return value: *the length of the string in bytes, that has been copied into pszOutBuf. */int JStringToChar(JNIEnv* env, jstring jstr, const char *pszEncoding, char* pszOutBuf, int nBufLen){int nRet = -1;jclass stringClass = NULL;jbyteArray byteElemArr = NULL;do{jmethodID cid = NULL;jstring jstrEncoding = NULL;const char* pszEnco = NULL;int nStrLen = 0;/* check the income parameters */if (NULL == jstr || NULL == env){break;}/* get the String class of java */stringClass = env->FindClass("java/lang/String");if (NULL == stringClass){break;}/* Get the method ID for the java.lang.String getBytes(String) */cid = env->GetMethodID(stringClass, "getBytes", "(java/lang/String;)[B");if (NULL == cid){break;}if(NULL == pszEncoding){pszEnco = "utf-8";}else{pszEnco = pszEncoding;}jstrEncoding = env->NewStringUTF(pszEnco);if (NULL == jstrEncoding){break;}/* get char string into array with designated encode */byteElemArr = (jbyteArray)env->CallObjectMethod(jstr, cid, jstrEncoding);if (NULL == byteElemArr){break;}nStrLen = (int)(env->GetArrayLength(byteElemArr));/* to return the length of the char string, if nBufLen is 0, or pszOutBuf is NULL */if (0 == nBufLen || NULL == pszOutBuf){nRet = nStrLen;break;}/* if the nBufLen < nStrLen, return failed */if (nBufLen < nStrLen){nRet = -2;break;}/* get the content of the byteArray, and copy into the out buffer */jbyte* pszBytes = env->GetByteArrayElements(byteElemArr, JNI_FALSE);if (NULL != pszBytes){memcpy(pszOutBuf, pszBytes, nStrLen);pszOutBuf[nStrLen] = 0;nRet = nStrLen;}}while(0);/* Free local references */if (NULL != byteElemArr){env->DeleteLocalRef(byteElemArr);}if (NULL != stringClass){env->DeleteLocalRef(stringClass);}return nRet;}