JNI 学习笔记(一)——字符串字符集转换

以下方式 总归 还是在使用使用java的string:"java/lang/String"


治根的办法 还是完整地在native code 中实现。推荐可以使用开源代码icu 或者iconv


android本身也是用了开源的库: iconv,只默认是未对外导出。


先放段代码作为开头,本段主要调用java中到构造函数,本段代码实现,字符串字符集转换。


jstring
MyNewString(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,"", "([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 
#include 
#include 

/*
 * 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, "", "([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;
}



 
  
 
  
 
  
 
 

你可能感兴趣的:(Jni)