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を完全に使用することはできないので、現在の多くのアプリケーションでは、変換は依然として必要です.
二、変換方法
概念を明確にすると、操作がはっきりします.以下、文字ストリームの方向によってそれぞれ説明する
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;
}