Base64编解码Android和ios的例子,补充JNI中的例子

1.在Android中java层提供了工具类:android.util.Base64;

 

    里面都是静态方法,方便直接使用:

 

    使用方法如下:

 

   

Java代码  收藏代码
  1. // Base64 编码:  
  2.         byte [] encode = Base64.encode("Hello, World".getBytes(), Base64.DEFAULT);  
  3.           
  4.         String enc = new String(encode);  
  5.           
  6.         Log.d("","base 64 encode = " + enc);  
  7.           
  8.         // Base64 解码:  
  9.         byte [] result = Base64.decode("SGVsbG8sIFdvcmxk", Base64.DEFAULT);  
  10.           
  11.         String res = new String(result);  
  12.           
  13.         Log.d("", "base 64 result = " + res);  

 

 

   例子演示了将"Hello, World"编码成"SGVsbG8sIFdvcmxk",然后又解码回来。简单易懂。

 

 

2.对于ios来说,有google的提供的一个工具箱来解决。

 

   网址:http://code.google.com/p/google-toolbox-for-mac/

 

   需要从里面找出3个文件:GTMBase64.h,GTMBase64.m,GTMDefines.h

 

    将这三个文件加入ios工程中即可使用了。

 

   例如:

 

   使用:

    NSLog(@"%@", [selfencodeBase64:@"Hello, World"]);

    NSLog(@"%@", [selfdecodeBase64:@"SGVsbG8sIFdvcmxk"]);

 

 调用的自己封装的函数:

 - (NSString *) encodeBase64:(NSString *) input{

    NSData *data = [inputdataUsingEncoding:NSUTF8StringEncodingallowLossyConversion:YES];

    data = [GTMBase64 encodeData:data];

    NSString *base64String = [[NSStringalloc] initWithData:dataencoding:NSUTF8StringEncoding];

    return base64String;

}

 

- (NSString *) decodeBase64:(NSString *) input{

    NSData *data = [inputdataUsingEncoding:NSUTF8StringEncodingallowLossyConversion:YES];

    data = [GTMBase64 decodeData:data];

    NSString *string = [[NSStringalloc] initWithData:dataencoding:NSUTF8StringEncoding];

    return string;

}

 

3.在Android中,我们也可以将base64的编解码算法放到jni中,这样也是比较方便的。

  

   对应的c中算法如下:

 

  

C代码  收藏代码
  1. #include "com_example_base64test_JniTest.h"  
  2.   
  3. #include <stdlib.h>  
  4.   
  5.   
  6. #include <android/log.h> // 这个是输出LOG所用到的函数所在的路径  
  7.   
  8. #define LOG_TAG    "JNILOG" // 这个是自定义的LOG的标识  
  9. #undef LOG // 取消默认的LOG  
  10.   
  11. #define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
  12. #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
  13. #define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
  14. #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
  15. #define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) // 定义LOG类型  
  16.   
  17. const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";  
  18. char* base64_encode(const char* data, int data_len);  
  19. char *base64_decode(const char* data, int data_len);  
  20. static char find_pos(char ch);  
  21.   
  22.   
  23. /* 
  24.  * Class:     com_example_base64test_JniTest 
  25.  * Method:    encode 
  26.  * Signature: (Ljava/lang/String;)Ljava/lang/String; 
  27.  */  
  28. JNIEXPORT jstring JNICALL Java_com_example_base64test_JniTest_encode  
  29.   (JNIEnv *env, jobject obj, jstring string)  
  30. {  
  31.   
  32.     // 先将jstring转换成char*  
  33.     char *t = 0;  
  34.     jclass clsstring = env->FindClass("java/lang/String");  
  35.     jstring strencode = env->NewStringUTF("utf-8");  
  36.     jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");  
  37.     jbyteArray barr= (jbyteArray)env->CallObjectMethod(string, mid, strencode);  
  38.     jsize alen = env->GetArrayLength(barr);  
  39.     jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);  
  40.     if (alen > 0)  
  41.     {  
  42.     t = (char*)malloc(alen + 1);  
  43.     memcpy(t, ba, alen);  
  44.     t[alen] = 0;  
  45.     }  
  46.     env->ReleaseByteArrayElements(barr, ba, 0);  
  47.   
  48.     // 此时的t里面有了jstring的内容  
  49.     int i = 0;  
  50.     int j = strlen(t);  
  51.     char *enc = base64_encode(t, j);  
  52.     int len = strlen(enc);  
  53.     char *dec = base64_decode(enc, len);  
  54.     LOGD("\noriginal: %s\n", t);  
  55.     LOGD("\nencoded : %s\n", enc);  
  56.     LOGD("\ndecoded : %s\n", dec);  
  57.     free(enc);  
  58.     free(dec);  
  59.   
  60.     // 将base64编码后的char转换成jstring返回给java层  
  61. //    jclass strClass = env->FindClass("Ljava/lang/String;");  
  62.     jclass strClass = env->FindClass("java/lang/String");  
  63.     jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");  
  64.     jbyteArray bytes = env->NewByteArray(strlen(enc));  
  65.     env->SetByteArrayRegion(bytes, 0, strlen(enc), (jbyte*)enc);  
  66.     jstring encoding = env->NewStringUTF("UTF-8");  
  67. //    jchar encoding_name[] = { 'U', 'T', 'F', '-', '8'};  
  68. //    jstring encoding = env->NewString(encoding_name, 5);  
  69.     return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);  
  70.   
  71. //    jbyte buffer[] = /* UTF8 encoding buffer */  
  72. //  
  73. //    jbyteArray bytes = env->NewByteArray(sizeof(buffer));  
  74. //  
  75. //    env->SetByteArrayRegion(bytes, 0, sizeof(buffer), buffer);  
  76.   
  77. //    return bytes;  
  78. }  
  79.   
  80. /* 
  81.  * Class:     com_example_base64test_JniTest 
  82.  * Method:    decode 
  83.  * Signature: (Ljava/lang/String;)Ljava/lang/String; 
  84.  */  
  85. JNIEXPORT jstring JNICALL Java_com_example_base64test_JniTest_decode  
  86.   (JNIEnv *env, jobject obj, jstring base)  
  87. {  
  88.     // 先将jstring转换成char*  
  89.     char *t = 0;  
  90.     jclass clsstring = env->FindClass("java/lang/String");  
  91.     jstring strencode = env->NewStringUTF("utf-8");  
  92.     jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");  
  93.     jbyteArray barr= (jbyteArray)env->CallObjectMethod(base, mid, strencode);  
  94.     jsize alen = env->GetArrayLength(barr);  
  95.     jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);  
  96.     if (alen > 0)  
  97.     {  
  98.     t = (char*)malloc(alen + 1);  
  99.     memcpy(t, ba, alen);  
  100.     t[alen] = 0;  
  101.     }  
  102.     env->ReleaseByteArrayElements(barr, ba, 0);  
  103.   
  104.     // 此时的t里面有了jstring的内容  
  105.     int i = 0;  
  106.     int j = strlen(t);  
  107. //    char *enc = base64_encode(t, j);  
  108. //    int len = strlen(enc);  
  109.     char *dec = base64_decode(t, j);  
  110.     LOGD("\noriginal: %s\n", t);  
  111. //    LOGD("\nencoded : %s\n", enc);  
  112.     LOGD("\ndecoded : %s\n", dec);  
  113. //    free(enc);  
  114.     free(dec);  
  115.   
  116.     // 将base64编码后的char转换成jstring返回给java层  
  117. //    jclass strClass = env->FindClass("Ljava/lang/String;");  
  118.     jclass strClass = env->FindClass("java/lang/String");  
  119.     jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");  
  120.     jbyteArray bytes = env->NewByteArray(strlen(dec));  
  121.     env->SetByteArrayRegion(bytes, 0, strlen(dec), (jbyte*)dec);  
  122.     jstring encoding = env->NewStringUTF("utf-8");  
  123.     jobject result = env->NewObject(strClass, ctorID, bytes, encoding);  
  124.     return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);  
  125. //    return result;  
  126. //    return bytes;  
  127. }  
  128.   
  129. /* */  
  130. char *base64_encode(const char* data, int data_len)  
  131. {  
  132.     //int data_len = strlen(data);  
  133.     int prepare = 0;  
  134.     int ret_len;  
  135.     int temp = 0;  
  136.     char *ret = NULL;  
  137.     char *f = NULL;  
  138.     int tmp = 0;  
  139.     char changed[4];  
  140.     int i = 0;  
  141.     ret_len = data_len / 3;  
  142.     temp = data_len % 3;  
  143.     if (temp > 0)  
  144.     {  
  145.         ret_len += 1;  
  146.     }  
  147.     ret_len = ret_len*4 + 1;  
  148.     ret = (char *)malloc(ret_len);  
  149.   
  150.     if ( ret == NULL)  
  151.     {  
  152.         LOGD("No enough memory.\n");  
  153.         exit(0);  
  154.     }  
  155.     memset(ret, 0, ret_len);  
  156.     f = ret;  
  157.     while (tmp < data_len)  
  158.     {  
  159.         temp = 0;  
  160.         prepare = 0;  
  161.         memset(changed, '\0', 4);  
  162.         while (temp < 3)  
  163.         {  
  164.             //printf("tmp = %d\n", tmp);  
  165.             if (tmp >= data_len)  
  166.             {  
  167.                 break;  
  168.             }  
  169.             prepare = ((prepare << 8) | (data[tmp] & 0xFF));  
  170.             tmp++;  
  171.             temp++;  
  172.         }  
  173.         prepare = (prepare<<((3-temp)*8));  
  174.         //printf("before for : temp = %d, prepare = %d\n", temp, prepare);  
  175.         for (i = 0; i < 4 ;i++ )  
  176.         {  
  177.             if (temp < i)  
  178.             {  
  179.                 changed[i] = 0x40;  
  180.             }  
  181.             else  
  182.             {  
  183.                 changed[i] = (prepare>>((3-i)*6)) & 0x3F;  
  184.             }  
  185.             *f = base[changed[i]];  
  186.             //printf("%.2X", changed[i]);  
  187.             f++;  
  188.         }  
  189.     }  
  190.     *f = '\0';  
  191.   
  192.     return ret;  
  193.   
  194. }  
  195. /* */  
  196. static char find_pos(char ch)  
  197. {  
  198.     char *ptr = (char*)strrchr(base, ch);//the last position (the only) in base[]  
  199.     return (ptr - base);  
  200. }  
  201. /* */  
  202. char *base64_decode(const char *data, int data_len)  
  203. {  
  204.     int ret_len = (data_len / 4) * 3;  
  205.     int equal_count = 0;  
  206.     char *ret = NULL;  
  207.     char *f = NULL;  
  208.     int tmp = 0;  
  209.     int temp = 0;  
  210.     char need[3];  
  211.     int prepare = 0;  
  212.     int i = 0;  
  213.     if (*(data + data_len - 1) == '=')  
  214.     {  
  215.         equal_count += 1;  
  216.     }  
  217.     if (*(data + data_len - 2) == '=')  
  218.     {  
  219.         equal_count += 1;  
  220.     }  
  221.     if (*(data + data_len - 3) == '=')  
  222.     {//seems impossible  
  223.         equal_count += 1;  
  224.     }  
  225.     switch (equal_count)  
  226.     {  
  227.     case 0:  
  228.         ret_len += 4;//3 + 1 [1 for NULL]  
  229.         break;  
  230.     case 1:  
  231.         ret_len += 4;//Ceil((6*3)/8)+1  
  232.         break;  
  233.     case 2:  
  234.         ret_len += 3;//Ceil((6*2)/8)+1  
  235.         break;  
  236.     case 3:  
  237.         ret_len += 2;//Ceil((6*1)/8)+1  
  238.         break;  
  239.     }  
  240.     ret = (char *)malloc(ret_len);  
  241.     if (ret == NULL)  
  242.     {  
  243.         LOGD("No enough memory.\n");  
  244.         exit(0);  
  245.     }  
  246.     memset(ret, 0, ret_len);  
  247.     f = ret;  
  248.     while (tmp < (data_len - equal_count))  
  249.     {  
  250.         temp = 0;  
  251.         prepare = 0;  
  252.         memset(need, 0, 4);  
  253.         while (temp < 4)  
  254.         {  
  255.             if (tmp >= (data_len - equal_count))  
  256.             {  
  257.                 break;  
  258.             }  
  259.             prepare = (prepare << 6) | (find_pos(data[tmp]));  
  260.             temp++;  
  261.             tmp++;  
  262.         }  
  263.         prepare = prepare << ((4-temp) * 6);  
  264.         for (i=0; i<3 ;i++ )  
  265.         {  
  266.             if (i == temp)  
  267.             {  
  268.                 break;  
  269.             }  
  270.             *f = (char)((prepare>>((2-i)*8)) & 0xFF);  
  271.             f++;  
  272.         }  
  273.     }  
  274.     *f = '\0';  
  275.     return ret;  
  276. }  

 

    不过这个例子里面,log打印的都是正确的,可是返回到java层的确是乱码,这个问题暂时还没有解决。希望有明白的同志告知一下。谢谢。工程附件中。

posted @ 2014-07-25 13:02  pansly  阅读(913)  评论(0编辑  收藏  举报