JNI文字変換中国語文字化けしの処理方法

3000 ワード

一.関連概念java内部は16 bitのunicode符号化(UTF-16)を用いて文字列を表すもので、中国語と英語にかかわらず2バイトである.jni内部はUTF-8符号化を用いて文字列を表し、UTF-8は変長符号化unicodeであり、一般的にascii文字は1バイト、中国語は3バイトである.c/c++は元のデータを使用し、asciiは1バイトで、中国語は一般的にGB 2312符号化で、1つの漢字を2バイトで表す.
概念を明確にすると、操作がはっきりします.以下、文字ストリームの方向によってそれぞれ説明する
1、java --> c/c++
この場合、java呼び出し時に使用されるのはUTF-16符号化文字列であり、jvmはこの文字列をjniに伝え、c/c++で得られる入力はjstringであり、この場合、jniが提供する2つの関数を利用することができ、1つはGetStringUTFcharsであり、この関数はUTF-8符号化文字列を得る.もう1つはGetStringCharsというUTF-16符号化が得られる文字列です.その関数にかかわらず、得られた文字列に中国語が含まれている場合、GB 2312の符号化にさらに変換する必要がある.概略図は以下の通りである:String        (UTF-16)           | [java]    | --------------------  JNI呼び出し[cpp]     |           v        jstring         (UTF-16)           |    +--------+---------+  |GetStringChars    |GetStringUTFChars  |                  |  v                  v wchar_t*           char* (UTF_16)           (UTF-8)
2、c/c++ --> java
jniはjavaに返される文字列で、c/c++はまずこの文字列をUTF-8またはUTF-16形式に変換し、NewStringUTFまたはNewStringでjstringにカプセル化しjavaに返せばよい.
       String        (UTF-16)           ^           | [java]    | --------------------  JNIは[cpp]を返す     |        jstring         (UTF-16)           ^           |    +--------+---------+  ^                  ^  |                  |  |NewString         |NewStringUTF wchar_t*          char* (UTF_16)          (UTF-8)
    文字列に中国語文字が含まれておらず、標準的なasciiコードである場合、GetStringUTFchars/NewStringUTFを使用すれば済む.この場合、UTF-8符号化とascii符号化は一致し、変換する必要がないからである.
    しかし、文字列に中国語文字がある場合は、c/c++部分で符号化変換を行う必要があります.UTF 8/16の符号化をGB 2312に変換する2つの変換関数が必要です.一つはGB 2312をUTF 8/16に回すことです.
   ここで説明すると、linuxとwin 32はwcharをサポートしているが、これは実際には幅16 bitのunicode符号化UTF 16であるため、c/c++プログラムでwcharタイプを完全に使用すると、理論的にはこのような変換は必要ない.しかし、実際には、charの代わりにwcharを完全に使用することはできないので、現在の多くのアプリケーションでは、変換は依然として必要です.
二、変換方法
#include "stdafx.h"
#include "student.h"
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <Windows.h>
#include <iostream>
using namespace std;

char* jstringToWindows( JNIEnv *env, jstring jstr )
{ //UTF8/16   gb2312
	int length = (env)->GetStringLength(jstr );
	const jchar* jcstr = (env)->GetStringChars(jstr, 0 );
	char* rtn = (char*)malloc( length*2+1 );
	int size = 0;
	size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
	if( size <= 0 )
		return NULL;
	(env)->ReleaseStringChars(jstr, jcstr );
	rtn[size] = 0;
	return rtn;
}

jstring WindowsTojstring( JNIEnv* env, const char* str )
{//gb2312   utf8/16
	jstring rtn = 0;
	int slen = strlen(str);
	unsigned short * buffer = 0;
	if( slen == 0 )
		rtn = (env)->NewStringUTF(str );
	else
	{
		int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
		buffer = (unsigned short *)malloc( length*2 + 1 );
		if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
			rtn = (env)->NewString(  (jchar*)buffer, length );
	}
	if( buffer )
		free( buffer );
	
	return rtn;
}