Base64编解码Android跟ios的例子,补充JNI中的例子
1.在Android中java层提供了工具类:android.util.Base64;
里面都是静态方法,方便直接使用:
使用方法如下:
// Base64 编码: byte [] encode = Base64.encode("Hello, World".getBytes(), Base64.DEFAULT); String enc = new String(encode); Log.d("","base 64 encode = " + enc); // Base64 解码: byte [] result = Base64.decode("SGVsbG8sIFdvcmxk", Base64.DEFAULT); String res = new String(result); 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 = [input dataUsingEncoding:NSUTF8StringEncodingallowLossyConversion:YES];
data = [GTMBase64 encodeData:data];
NSString *base64String = [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding];
return base64String;
}
- (NSString *) decodeBase64:(NSString *) input{
NSData *data = [input dataUsingEncoding:NSUTF8StringEncodingallowLossyConversion:YES];
data = [GTMBase64 decodeData:data];
NSString *string = [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding];
return string;
}
3.在Android中,我们也可以将base64的编解码算法放到jni中,这样也是比较方便的。
对应的c中算法如下:
#include "com_example_base64test_JniTest.h" #include <stdlib.h> #include <android/log.h> // 这个是输出LOG所用到的函数所在的路径 #define LOG_TAG "JNILOG" // 这个是自定义的LOG的标识 #undef LOG // 取消默认的LOG #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) // 定义LOG类型 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) // 定义LOG类型 #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) // 定义LOG类型 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) // 定义LOG类型 #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,LOG_TAG,__VA_ARGS__) // 定义LOG类型 const char base[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; char* base64_encode(const char* data, int data_len); char *base64_decode(const char* data, int data_len); static char find_pos(char ch); /* * Class: com_example_base64test_JniTest * Method: encode * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_base64test_JniTest_encode (JNIEnv *env, jobject obj, jstring string) { // 先将jstring转换成char* char *t = 0; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr= (jbyteArray)env->CallObjectMethod(string, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { t = (char*)malloc(alen + 1); memcpy(t, ba, alen); t[alen] = 0; } env->ReleaseByteArrayElements(barr, ba, 0); // 此时的t里面有了jstring的内容 int i = 0; int j = strlen(t); char *enc = base64_encode(t, j); int len = strlen(enc); char *dec = base64_decode(enc, len); LOGD("\noriginal: %s\n", t); LOGD("\nencoded : %s\n", enc); LOGD("\ndecoded : %s\n", dec); free(enc); free(dec); // 将base64编码后的char转换成jstring返回给java层 // jclass strClass = env->FindClass("Ljava/lang/String;"); jclass strClass = env->FindClass("java/lang/String"); jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(enc)); env->SetByteArrayRegion(bytes, 0, strlen(enc), (jbyte*)enc); jstring encoding = env->NewStringUTF("UTF-8"); // jchar encoding_name[] = { 'U', 'T', 'F', '-', '8'}; // jstring encoding = env->NewString(encoding_name, 5); return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); // jbyte buffer[] = /* UTF8 encoding buffer */ // // jbyteArray bytes = env->NewByteArray(sizeof(buffer)); // // env->SetByteArrayRegion(bytes, 0, sizeof(buffer), buffer); // return bytes; } /* * Class: com_example_base64test_JniTest * Method: decode * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_base64test_JniTest_decode (JNIEnv *env, jobject obj, jstring base) { // 先将jstring转换成char* char *t = 0; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr= (jbyteArray)env->CallObjectMethod(base, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { t = (char*)malloc(alen + 1); memcpy(t, ba, alen); t[alen] = 0; } env->ReleaseByteArrayElements(barr, ba, 0); // 此时的t里面有了jstring的内容 int i = 0; int j = strlen(t); // char *enc = base64_encode(t, j); // int len = strlen(enc); char *dec = base64_decode(t, j); LOGD("\noriginal: %s\n", t); // LOGD("\nencoded : %s\n", enc); LOGD("\ndecoded : %s\n", dec); // free(enc); free(dec); // 将base64编码后的char转换成jstring返回给java层 // jclass strClass = env->FindClass("Ljava/lang/String;"); jclass strClass = env->FindClass("java/lang/String"); jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(dec)); env->SetByteArrayRegion(bytes, 0, strlen(dec), (jbyte*)dec); jstring encoding = env->NewStringUTF("utf-8"); jobject result = env->NewObject(strClass, ctorID, bytes, encoding); return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); // return result; // return bytes; } /* */ char *base64_encode(const char* data, int data_len) { //int data_len = strlen(data); int prepare = 0; int ret_len; int temp = 0; char *ret = NULL; char *f = NULL; int tmp = 0; char changed[4]; int i = 0; ret_len = data_len / 3; temp = data_len % 3; if (temp > 0) { ret_len += 1; } ret_len = ret_len*4 + 1; ret = (char *)malloc(ret_len); if ( ret == NULL) { LOGD("No enough memory.\n"); exit(0); } memset(ret, 0, ret_len); f = ret; while (tmp < data_len) { temp = 0; prepare = 0; memset(changed, '\0', 4); while (temp < 3) { //printf("tmp = %d\n", tmp); if (tmp >= data_len) { break; } prepare = ((prepare << 8) | (data[tmp] & 0xFF)); tmp++; temp++; } prepare = (prepare<<((3-temp)*8)); //printf("before for : temp = %d, prepare = %d\n", temp, prepare); for (i = 0; i < 4 ;i++ ) { if (temp < i) { changed[i] = 0x40; } else { changed[i] = (prepare>>((3-i)*6)) & 0x3F; } *f = base[changed[i]]; //printf("%.2X", changed[i]); f++; } } *f = '\0'; return ret; } /* */ static char find_pos(char ch) { char *ptr = (char*)strrchr(base, ch);//the last position (the only) in base[] return (ptr - base); } /* */ char *base64_decode(const char *data, int data_len) { int ret_len = (data_len / 4) * 3; int equal_count = 0; char *ret = NULL; char *f = NULL; int tmp = 0; int temp = 0; char need[3]; int prepare = 0; int i = 0; if (*(data + data_len - 1) == '=') { equal_count += 1; } if (*(data + data_len - 2) == '=') { equal_count += 1; } if (*(data + data_len - 3) == '=') {//seems impossible equal_count += 1; } switch (equal_count) { case 0: ret_len += 4;//3 + 1 [1 for NULL] break; case 1: ret_len += 4;//Ceil((6*3)/8)+1 break; case 2: ret_len += 3;//Ceil((6*2)/8)+1 break; case 3: ret_len += 2;//Ceil((6*1)/8)+1 break; } ret = (char *)malloc(ret_len); if (ret == NULL) { LOGD("No enough memory.\n"); exit(0); } memset(ret, 0, ret_len); f = ret; while (tmp < (data_len - equal_count)) { temp = 0; prepare = 0; memset(need, 0, 4); while (temp < 4) { if (tmp >= (data_len - equal_count)) { break; } prepare = (prepare << 6) | (find_pos(data[tmp])); temp++; tmp++; } prepare = prepare << ((4-temp) * 6); for (i=0; i<3 ;i++ ) { if (i == temp) { break; } *f = (char)((prepare>>((2-i)*8)) & 0xFF); f++; } } *f = '\0'; return ret; }
不过这个例子里面,log打印的都是正确的,可是返回到java层的确是乱码,这个问题暂时还没有解决。希望有明白的同志告知一下。谢谢。工程附件中。