注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

还东国的博客

行之苟有恒,久久自芬芳

 
 
 

日志

 
 

Android开发之三十五AndroidStudio中Char*和Jstring的相互转换  

2015-07-22 20:26:21|  分类: Android |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Android开发之三十五AndroidStudioChar*Jstring的相互转换

在处理FIDO的字符串来回交换的过程中,一般要处理jstring到时char*(unsinged char*)的转换,这样来回控制的数据通信就会通畅无阻。

但是在实际使用中发现了这样还有那样的错误。从网上找了N多的解决方法,但是都是在细节上有一些不同,导致了不同的结果,甚至是崩溃。

先说再把字符串传入C库中时,JstringChar*,用下面的就JstringToChar可以解决问题,但是在回传字符串反向转换时,程序直接崩溃了。

网上的方法大家都知道,基本上很少有人验证过,就是转来转去。结果是到最终谁也不知道到底能不能用。这次估计遇到的就是这种情况。

后来在一个兄弟的网站上看到

http://blog.csdn.net/ztp800201/article/details/7388189,说有中文的如何处理,代码如下:

jstring   CharTojstring(JNIEnv*   env,   char*   str)

{

    jsize   len   =   strlen(str);

 

    jclass   clsstring   =   (*env)->FindClass(env, "java/lang/String");

    jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");

 

    jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "<init>",   "([BLjava/lang/String;)V");

    jbyteArray   barr   =   (*env)-> NewByteArray(env,len);

 

    (*env)-> SetByteArrayRegion(env,barr,0,len,(jbyte*)str);

    return (jstring)(*env)-> NewObject(env,clsstring,mid,barr,strencode);

}

发现和原有的代码下面的红色部分,不同的就是少了一个L。回想起前面有一个帖子确实说过把L去除。即“把那个大写的L和后面的分号去掉。大写的L是用在定义字段类型和方法签名上的。

去除后就OK了。但是是不是在C++C中有这种区别,还是不敢肯定,毕竟没有实际测试,回头有时间真刀真枪的做一次测试。

L全限定名;,比如String, 其签名为Ljava/lang/util/String;(注意一面有分号)这在C++里代表一个类,但是在C里没有这个类的概念,所以是不是不需要这么做。更详细的可查看相关“JNI方法名,数据类型和方法签名”的资料。

代码见下:

jstring stoJstring(JNIEnv* env, const char* pat)
{
//    jclass strClass = (*env)->FindClass(env,"Ljava/lang/String;");
//    jmethodID ctorID = (*env)->GetMethodID(env,strClass, "<init>", "([BLjava/lang/String;)V");
//    jbyteArray bytes = (*env)->NewByteArray(env,strlen(pat));
//    (*env)->SetByteArrayRegion(env,bytes, 0, strlen(pat), (jbyte*)pat);
//    jstring encoding = (*env)->NewStringUTF(env,"utf-8");
//    return (jstring)(*env)->NewObject(env,strClass, ctorID, bytes, encoding);
   
jsize len = sizeof(GeneralUvt);//strlen(pat);
   
jclass strClass = (*env)->FindClass(env,"java/lang/String");
    jstring strEncode = (*env)
->NewStringUTF(env,"utf-8");
    jmethodID jmid = (*env)
->GetMethodID(env,strClass,"<init>","([BLjava/lang/String;)V");
    jbyteArray jba = (*env)
->NewByteArray(env,len);
    (*env)
->SetByteArrayRegion(env,jba,0,len,(jbyte*)pat);
   
return (jstring)(*env)->NewObject(env,strClass,jmid,jba,strEncode);

}

JNIEXPORT   void   JNICALL   JavaStringToChars  (JNIEnv*env,jstring cmd)
 {
    
char*   t;
     t   =   (
char*)(*env)->GetStringUTFChars(env,cmd,0);
 }

 
char* JstringToChar(JNIEnv *env, jstring jstr)
 {
    
char * rtn = 0;
     jclass clsstring = (*env)
->FindClass(env,"java/lang/String");
     jstring strencode = (*env)
->NewStringUTF(env,"UTF-8");
     jmethodID mid = (*env)
->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B");
     jbyteArray barr= (jbyteArray)(*env)
->CallObjectMethod(env,jstr,mid,strencode);
     jsize alen = (*env)
->GetArrayLength(env,barr);
     jbyte * ba = (*env)
->GetByteArrayElements(env,barr,JNI_FALSE);
    
if(alen > 0)
     {
         rtn = (
char*)malloc(alen+1); //new char[alen+1];
        
memcpy(rtn,ba,alen);
         rtn[alen]=
0;
     }
     (*env)
->ReleaseByteArrayElements(env,barr,ba,0);

    
return rtn;
 }

另外一个坑就是jsize strlen,程序是unigned char*里面难免有0,这样对Strlen来说可能长度就不对了。调试的结果就是返回的字符串长度非常短。后来看了看程序,还是怀疑是不是长度的问题,于是把这个长度函数换成了实际的长度的sizeof,这样发现果然就OK了。

细节处处见精神,不注重细节就总在细节上栽跟头。

  评论这张
 
阅读(299)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017