要求:
在java当中传入一个字符串,在JNI当中实现打印;
问题:
会出现乱码;
产生原因:
- Java 采用Utf-16编码 字符占2字节 16bit
- JNI采用Utf-8编码 因为占用1字节 中文3字节
- C/C++采用Ascii编码 中文采用GB2312编码,中文2个字节
解决方案一
JNIEXPORT jobject JNICALL Java_com_zzqqiang_1Test_chineseChars
(JNIEnv * env, jobject jobj, jstring in) {
//用于判断当前字符是重新分配内存copy过来的还是直接指向原来的内存
boolean scp;
char *c_str = (*env)->GetStringChars(env, in,&iscp);
if (iscp == JNI_TRUE) {
printf("is copy:JNI_TRUE\n");
} else if{
printf("is copy:JNI_FALSE\n");
}
int length = (*env)->GetStringLength(env,in);
const jchar *jcstr = (*env)->GetStringChars(env,in,NULL);
if (jcstr == NULL) {
return NULL;
}
//将jchar 转为char,+1是为了放置结束符,*2是为了分配足够的空间
char *rtn = (char *)malloc(sizeof(char)*length*2+1);
//初始化内存
memset(rtn,0,sizeof(char)*length*2+1);
int size = 0;
size = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)jcstr, length, rtn, sizeof(char) * 2*length + 1, NULL, NULL);
pringf("输出的中文字符为:%s",rtn);
return NULL;
}
//java
public class JniMain {
public native void chineseChars(String str);
public static void main(String[] args) {
JniMain jniMain = new JniMain();
jniMain.chineseChars("美图秀秀天下第一");
}
}
解决方案二
利用Java String字符串本身的特性,在构造的时候传入相应编码即可
public String(byte[] bytes, String charsetName) throws UnsupportedEncodingException {
throw new RuntimeException("Stub!");
}
JNIEXPORT jobject JNICALL Java_com_zzqqiang_1Test_chineseChars
(JNIEnv * env, jobject jobj, jstring in) {
char * c_str = "美图秀秀天下第一";
jclass str_cls = (*env)->FindClass(env,"java/lang/String");
//关于String构造函数的签名可以自己查阅,
jMethodID jmid = (*env)->GetMethodID(env,str_cls,"<init>","([BLjava/lang/String;)V");
jbyteArray bytes = (*env)->NewByteArray(env,strlen(c_str));
// 将Char * 赋值到 bytes
(*env)->SetByteArrayRegion(env, bytes, 0, strlen(c_str), c_str);
jstring charsetName = (*env)->NewStringUTF(env,"GB2312");
return (*env)->NewObject(env,str_cls,jmid,bytes,charsetName);
}
网友评论