1. 程式人生 > >jni中字元轉換原理

jni中字元轉換原理

一.相關概念 java內部是使用16bit的unicode編碼(UTF-16)來表示字串的,無論中文英文都是2位元組; jni內部是使用UTF-8編碼來表示字串的,UTF-8是變長編碼的unicode,一般ascii字元是1位元組,中文是3位元組; c/c++使用的是原始資料,ascii就是一個位元組了,中文一般是GB2312編碼,用兩個位元組來表示一個漢字。

明確了概念,操作就比較清楚了。下面根據字元流的方向來分別說明一下

1、java --> c/c++

這種情況中,java呼叫的時候使用的是UTF-16編碼的字串,jvm把這個字串傳給jni,c/c++得到的輸入是jstring,這個時候,可以利用jni提供的兩種函式,一個是GetStringUTFChars,這個函式將得到一個UTF-8編碼的字串;另一個是 GetStringChars這個將得到UTF-16編碼的字串。無論那個函式,得到的字串如果含有中文,都需要進一步轉化成GB2312的編碼。示意圖如下: String        (UTF-16)           | [java]    | --------------------  JNI 呼叫 [cpp]     |           v        jstring         (UTF-16)           |    +--------+---------+  |GetStringChars    |GetStringUTFChars  |                  |  v                  v wchar_t*           char* (UTF_16)           (UTF-8)

2、c/c++ --> java

jni返回給java的字串,c/c++首先應該負責把這個字串變成UTF-8或者UTF-16格式,然後通過NewStringUTF或者NewString來把它封裝成jstring,返回給java就可以了。

       String        (UTF-16)           ^           | [java]    | --------------------  JNI 返回 [cpp]     |        jstring         (UTF-16)           ^           |    +--------+---------+  ^                  ^  |                  |  |NewString         |NewStringUTF wchar_t*          char* (UTF_16)          (UTF-8)

    如果字串中不含中文字元,只是標準的ascii碼,那麼使用GetStringUTFChars/NewStringUTF就可以搞定了,因為這種情況下,UTF-8編碼和ascii編碼是一致的,不需要轉換。

    但是如果字串中有中文字元,那麼在c/c++部分進行編碼轉換就是一個必須了。我們需要兩個轉換函式,一個是把UTF8/16的編碼轉成GB2312;一個是把GB2312轉成UTF8/16。

   這裡要說明一下:linux和win32都支援wchar,這個事實上就是寬度為16bit的unicode編碼UTF16,所以,如果我們的 c/c++程式中完全使用wchar型別,那麼理論上是不需要這種轉換的。但是實際上,我們不可能完全用wchar來取代char的,所以就目前大多數應用而言,轉換仍然是必須的。

二、轉換方法

#include "stdafx.h"

#include "student.h"

#include <stdlib.h>

#include <malloc.h>

#include <memory.h>

#include <Windows.h>

#include <iostream>

using namespace std;


char* jstringToWindows( JNIEnv *env, jstring jstr )

{ //UTF8/16轉換成gb2312

int length = (env)->GetStringLength(jstr );

const jchar* jcstr = (env)->GetStringChars(jstr, 0 );

char* rtn = (char*)malloc( length*2+1 );

int size = 0;

size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );

if( size <= 0 )

return NULL;

(env)->ReleaseStringChars(jstr, jcstr );

rtn[size] = 0;

return rtn;

}


jstring WindowsTojstring( JNIEnv* env, const char* str )

{//gb2312轉換成utf8/16

jstring rtn = 0;

int slen = strlen(str);

unsigned short * buffer = 0;

if( slen == 0 )

rtn = (env)->NewStringUTF(str );

else

{

int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );

buffer = (unsigned short *)malloc( length*2 + 1 );

if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )

rtn = (env)->NewString( (jchar*)buffer, length );

}

if( buffer )

free( buffer );


return rtn;

}

轉載:https://blog.csdn.net/earbao/article/details/8955338?utm_source=copy