假如这个世界上只剩下你一个人,当你正坐在屋子里的时候,这时突然响起了敲门声...

JNI的中文问题

上一篇 / 下一篇  2008-05-05 20:47:58

查看( 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.s w$E Z"T^`5`7A0 {
]!u&S7P/B/k0   int length = env->GetStringLength(jstr );
[ NJs1["D7X e0   const jchar* jcstr = env->GetStringChars(jstr, 0 );
e2F;_3vt%P$\"`*O0   char* rtn = (char*)malloc( length*2+1 );
/|Wn8O-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 ei Y$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.J W
}ITPUB个人空间 Zn$X9a _8x1pb8D
ITPUB个人空间nEHytk+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 )
OL3R7kO;O}0     rtn = env->NewStringUTF( str ); ITPUB个人空间&F'lU EPf
  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!Rh5kwxg [ U0 char* jstringToNative( JNIEnv  *env, jstring jstr )ITPUB个人空间5G&b Q^z)lU/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];   
L9E6EjO6pw6@0   MultiByteToWideChar( CP_UTF8, 0, pstr, -1, lpwsz, nLen );ITPUB个人空间(sDZ^0F`O&psC@ ~i
  int nLen1 = WideCharToMultiByte( CP_ACP, 0, lpwsz, nLen, NULL, NULL, NULL, NULL );    ITPUB个人空间`1i7Q3im
  LPSTR lpsz = new CHAR[nLen1];ITPUB个人空间mq0F5x gIV]
  int size = 0;ITPUB个人空间1ye$i2P/k n
  size = WideCharToMultiByte( CP_ACP, 0, lpwsz, nLen, lpsz, nLen1, NULL, NULL );ITPUB个人空间_ |rcY^a
  if( size <= 0 ){
7cQ0J0qt@y&k5v y(_:_0       delete [] lpwsz;
T*h;O&QoZ5D w0       return NULL;
9hO!I%M(S0   }ITPUB个人空间 hf/Ys/Sq?
  env->ReleaseStringUTFChars(jstr, pstr );ITPUB个人空间&f'K l0S7j:u~%b:I:t
  delete [] lpwsz;ITPUB个人空间 q&})v {cNw
  return lpsz;ITPUB个人空间N \C {`m"M
}
L p3wL3Ma'F!W0 问题虽然解决了,但是我却不求甚解,为什么直接通过env拿到unicode字串,然后转成多字节串不行,但是通过env拿到utf-8字串,然后转成unicode字串,再将这个unicode字串转成多字节串就能工作?ITPUB个人空间x m u.B)?1?'u

.VJc^9n`2U\zY0 如果大家有兴趣的话,不妨试试,用JNI调用RegOpenKeyEx这个API,就能验证我说的这个Case。哪位老大对JNI比较在行的话,可以在评论中告诉我,不甚感激。

TAG:

我来说两句

(可选)

日历

« 2008-05-17  
    123
45678910
11121314151617
18192021222324
25262728293031

数据统计

  • 访问量: 3859
  • 日志数: 83
  • 建立时间: 2008-02-08
  • 更新时间: 2008-04-25

RSS订阅

Open Toolbar