假如这个世界上只剩下你一个人,当你正坐在屋子里的时候,这时突然响起了敲门声...
JNI的中文问题
查看( 21 ) /
评论( 0 )
网上有一篇关于JNI中文问题的文章,写得很详细,http://www.vckbase.com/document/viewdoc/?id=1611ITPUB个人空间"JD?2\;p-Q2Z8G3O-lz
ITPUB个人空间0uJqeB5?
我在这里主要是想说说我碰到的一些问题,并且希望能从各位老大身上获得答案。
-GT1c Z(i;`iK0 ITPUB个人空间_P4VL3B%i
因为一直从事Java编程,基本上没有涉及过C++的开发,最近因为开源项目SWT Extension,不得已需要用JNI来实现一些系统Native功能。但是总是需要一些Java字符串对应C++的字符串的问题。一边情况下我都是使用SWT的TCHAR来解决问题,少部分情况需要传递Java String到JNI。然而少部分的这些Case总是在某些问题下出现乱码或者异常。我一直使用的是网上比较流行的中文编码解决方案:
;Xt*P"@ J d*l,|0 char* jstringToNative( JNIEnv *env, jstring jstr )
-u5l.sw$E Z"T^`5`7A0 {
]!u&S7P/B/k0 int length = env->GetStringLength(jstr );
[NJs1["D7Xe0 const jchar* jcstr = env->GetStringChars(jstr, 0 );
e2F;_3vt%P$\"`*O0 char* rtn = (char*)malloc( length*2+1 );
/|W n8O-O'EM0 int size = 0;
"~0sQp%e0 size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );ITPUB个人空间b'xa'[,R-p
if( size <= 0 )return NULL;ITPUB个人空间+c:A eiY$O*v$?
env->ReleaseStringChars(jstr, jcstr );ITPUB个人空间8_Gk+fl_3Y
rtn[size] = 0;ITPUB个人空间@%xn-Wz{#{3{-LU
return rtn;ITPUB个人空间:d } j"k.JW
}ITPUB个人空间 Zn$X9a_8x1pb8D
ITPUB个人空间nEHyt k+f [4m
jstring nativeTojstring( JNIEnv* env, char* str )
Q5s$ER%mfEg0 {ITPUB个人空间N:}k8c(k:A {
jstring rtn = 0;ITPUB个人空间s)vcg y'W`P
int slen = strlen(str);
3I [Z"x\cF"s0 unsigned short * buffer = 0;
3?L L-o ?$O$z7I7s*P-D0 if( slen == 0 )
O L3R7kO;O}0 rtn = env->NewStringUTF( str ); ITPUB个人空间&F'lUEPf
elseITPUB个人空间d+Ks"Q,La8dV4j$d(N
{ITPUB个人空间#q5l(`)V'?\
int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
&M5WJ7F@`"yU*h0 buffer = (unsigned short *)malloc( length*2 + 1 );
p[Ix)Cn9Aq0 if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )ITPUB个人空间}u'l;bl:x^x
rtn = env->NewString( (jchar*)buffer, length );ITPUB个人空间&FOP9CC \
}ITPUB个人空间$OV7O"}8]v
if( buffer )
&j,b#l|.Yj#{m0 free( buffer );ITPUB个人空间0Cw&b-e+}
return rtn;ITPUB个人空间.H(z{@Id
}
0gKfyz"~U*P0 ITPUB个人空间%g&A6iX J*Ob
一般情况下,这两个函数能够很好的工作。但是在读写注册表时,如果一个key的名字或者value的名字中包含了中文,jstringToNative的解决方案是不正确的,我在网上查了一下其它的关于Java访问注册表的开源项目,发现虽然它们都对字符串进行了处理,但依然存在着中文问题。我进行了数次尝试,但都没有成功。最后到了已经绝望的时候,用开头我提到的那篇文章中里说的最不可能用到的方法将问题成功地解决了:
Hv!R h5kwxg[ U0 char* jstringToNative( JNIEnv *env, jstring jstr )ITPUB个人空间5G&b Q^z)l U/oZi
{ITPUB个人空间gp g M*J:eGt
const char* pstr = env->GetStringUTFChars(jstr, false);ITPUB个人空间^v#dy }7eu{
int nLen = MultiByteToWideChar( CP_UTF8, 0, pstr, -1, NULL, NULL );ITPUB个人空间(EkqDY"|Zu
LPWSTR lpwsz = new WCHAR[nLen];
ITPUB个人空间0uJqeB5?
我在这里主要是想说说我碰到的一些问题,并且希望能从各位老大身上获得答案。
-GT1c Z(i;`iK0 ITPUB个人空间_P4VL3B%i
因为一直从事Java编程,基本上没有涉及过C++的开发,最近因为开源项目SWT Extension,不得已需要用JNI来实现一些系统Native功能。但是总是需要一些Java字符串对应C++的字符串的问题。一边情况下我都是使用SWT的TCHAR来解决问题,少部分情况需要传递Java String到JNI。然而少部分的这些Case总是在某些问题下出现乱码或者异常。我一直使用的是网上比较流行的中文编码解决方案:
;Xt*P"@ J d*l,|0 char* jstringToNative( JNIEnv *env, jstring jstr )
-u5l.sw$E Z"T^`5`7A0 {
]!u&S7P/B/k0 int length = env->GetStringLength(jstr );
[NJs1["D7Xe0 const jchar* jcstr = env->GetStringChars(jstr, 0 );
e2F;_3vt%P$\"`*O0 char* rtn = (char*)malloc( length*2+1 );
/|W n8O-O'EM0 int size = 0;
"~0sQp%e0 size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );ITPUB个人空间b'xa'[,R-p
if( size <= 0 )return NULL;ITPUB个人空间+c:A eiY$O*v$?
env->ReleaseStringChars(jstr, jcstr );ITPUB个人空间8_Gk+fl_3Y
rtn[size] = 0;ITPUB个人空间@%xn-Wz{#{3{-LU
return rtn;ITPUB个人空间:d } j"k.JW
}ITPUB个人空间 Zn$X9a_8x1pb8D
ITPUB个人空间nEHyt k+f [4m
jstring nativeTojstring( JNIEnv* env, char* str )
Q5s$ER%mfEg0 {ITPUB个人空间N:}k8c(k:A {
jstring rtn = 0;ITPUB个人空间s)vcg y'W`P
int slen = strlen(str);
3I [Z"x\cF"s0 unsigned short * buffer = 0;
3?L L-o ?$O$z7I7s*P-D0 if( slen == 0 )
O L3R7kO;O}0 rtn = env->NewStringUTF( str ); ITPUB个人空间&F'lUEPf
elseITPUB个人空间d+Ks"Q,La8dV4j$d(N
{ITPUB个人空间#q5l(`)V'?\
int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
&M5WJ7F@`"yU*h0 buffer = (unsigned short *)malloc( length*2 + 1 );
p[Ix)Cn9Aq0 if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )ITPUB个人空间}u'l;bl:x^x
rtn = env->NewString( (jchar*)buffer, length );ITPUB个人空间&FOP9CC \
}ITPUB个人空间$OV7O"}8]v
if( buffer )
&j,b#l|.Yj#{m0 free( buffer );ITPUB个人空间0Cw&b-e+}
return rtn;ITPUB个人空间.H(z{@Id
}
0gKfyz"~U*P0 ITPUB个人空间%g&A6iX J*Ob
一般情况下,这两个函数能够很好的工作。但是在读写注册表时,如果一个key的名字或者value的名字中包含了中文,jstringToNative的解决方案是不正确的,我在网上查了一下其它的关于Java访问注册表的开源项目,发现虽然它们都对字符串进行了处理,但依然存在着中文问题。我进行了数次尝试,但都没有成功。最后到了已经绝望的时候,用开头我提到的那篇文章中里说的最不可能用到的方法将问题成功地解决了:
Hv!R h5kwxg[ U0 char* jstringToNative( JNIEnv *env, jstring jstr )ITPUB个人空间5G&b Q^z)l U/oZi
{ITPUB个人空间gp g M*J:eGt
const char* pstr = env->GetStringUTFChars(jstr, false);ITPUB个人空间^v#dy }7eu{
int nLen = MultiByteToWideChar( CP_UTF8, 0, pstr, -1, NULL, NULL );ITPUB个人空间(EkqDY"|Zu
LPWSTR lpwsz = new WCHAR[nLen];