2008-09-15 8 views
12

में कैसे परिवर्तित करूं मान लें कि C++ पक्ष पर मेरा फ़ंक्शन नामक jstring प्रकार का चर लेता है। इस प्रकार मैं एक एएनएसआई स्ट्रिंग के लिए परिवर्तित कर सकते हैं:मैं jstring को wchar_t *

const char* ansiString = env->GetStringUTFChars(myString, 0); 

वहाँ

const wchar_t* unicodeString = हो रही का एक तरीका है ...

उत्तर

3

एक पोर्टेबल और मजबूत समाधान iconv उपयोग करने के लिए है, समझ के साथ कि आपको पता होना चाहिए कि आपके सिस्टम wchar_t का उपयोग एन्कोडिंग (उदाहरण के लिए, कई यूनिक्स सिस्टम पर यूटीएफ -32, यूटीएफ -32, उदाहरण के लिए)।

यदि आप तृतीय पक्ष कोड पर अपनी निर्भरता को कम करना चाहते हैं, तो आप अपने स्वयं के यूटीएफ -8 कनवर्टर को भी रोल-रोल कर सकते हैं। यूटीएफ -32 में परिवर्तित होने पर यह आसान है, यूटीएफ -16 के साथ कुछ हद तक कठिन है क्योंकि आपको सरोगेट जोड़े को भी संभालना है। :-P इसके अलावा, आपको non-shortest रूपों को अस्वीकार करने के लिए सावधान रहना चाहिए, या यह कुछ मामलों में सुरक्षा बग खोल सकता है।

+0

आप जेएसटींग को यूटीएफ -8 में परिवर्तित करने का सुझाव दे रहे हैं और फिर यूटीएफ -16 में परिवर्तित कर रहे हैं? क्या यह सचमुच आवश्यक है? – Rup

+0

@Rup jstrings पहले से ही यूटीएफ -8 हैं: "जेएनआई विभिन्न स्ट्रिंग प्रकारों का प्रतिनिधित्व करने के लिए संशोधित यूटीएफ -8 तारों का उपयोग करता है। संशोधित यूटीएफ -8 स्ट्रिंग जावा वीएम द्वारा उपयोग किए जाने वाले समान हैं। संशोधित यूटीएफ -8 तारों को एन्कोड किया गया है ताकि चरित्र अनुक्रम जिनमें केवल गैर-शून्य ASCII वर्ण होते हैं, प्रति वर्ण केवल एक बाइट का उपयोग करके प्रदर्शित किया जा सकता है, लेकिन सभी यूनिकोड वर्णों का प्रतिनिधित्व किया जा सकता है ..... जावा वीएम मानक यूटीएफ -8 के चार-बाइट प्रारूप को नहीं पहचानता है; इसके बजाए अपने दो-बार-तीन-बाइट प्रारूप का उपयोग करता है। " –

+0

@ b1naryatr0phy वास्तव में? jni.h मेरी प्रणाली पर (दोनों 1।6 और 1.7) में 'टाइपिफ अप शॉर्ट जचर' है, जो मुझे यूटीएफ -16 की तरह दिखता है। – Rup

0

यदि हमें क्रॉस प्लेटफ़ॉर्म-क्षमता में रुचि नहीं है, तो आप विंडोज़ में मल्टीबाइट टॉइडवायर फ़ंक्शन, या सहायक मैक्रोज़ ए 2 डब्ल्यू (रेफरी example) का उपयोग कर सकते हैं।

3

जेएनआई के पास GetStringChars() फ़ंक्शन भी है। रिटर्न टाइप कॉन्स जचर * है, jchar Win32 पर 16-बिट है, इसलिए इस तरह से wchar_t के साथ संगत होगा। सुनिश्चित नहीं है कि यह वास्तविक यूटीएफ -16 है या कुछ और ...

+0

क्या आपको पता है कि jchar का बाइट ऑर्डर Win32 wchar_t एक के साथ संगत है या नहीं? यह होना चाहिए, लेकिन यह सुनिश्चित करने के लिए शायद अच्छा है। :-) –

+0

jchar को हस्ताक्षरित छोटा करने के लिए टाइप किया गया है। मैंने इसे स्वयं नहीं किया है लेकिन मेरा अनुमान "हां" होगा। –

+0

char == jchar == हस्ताक्षरित 16 बिट्स –

0

बस env-> GetStringChars (myString, 0) का उपयोग करें; जावा अपनी प्रकृति से यूनिकोड पास करता है

2

मुझे पता है कि यह एक साल पहले पूछा गया था, लेकिन मुझे अन्य उत्तरों पसंद नहीं हैं इसलिए मैं जवाब देने जा रहा हूं। यहाँ कैसे हम अपने स्रोत में कर दिया गया है:

wchar_t * JavaToWSZ(JNIEnv* env, jstring string) 
{ 
    if (string == NULL) 
     return NULL; 
    int len = env->GetStringLength(string); 
    const jchar* raw = env->GetStringChars(string, NULL); 
    if (raw == NULL) 
     return NULL; 

    wchar_t* wsz = new wchar_t[len+1]; 
    memcpy(wsz, raw, len*2); 
    wsz[len] = 0; 

    env->ReleaseStringChars(string, raw); 

    return wsz; 
} 

संपादित: यह समाधान प्लेटफार्मों पर अच्छी तरह से काम जहां wchar_t 2 बाइट्स है, कुछ प्लेटफॉर्म एक 4 बाइट wchar_t जिस स्थिति में इस समाधान काम नहीं करेगा की है।

+2

यह समाधान गलत है। मैंने उस वजह से 12 घंटे चूसा। wchar_t और jchar आवश्यक नहीं हैं। इसके लिए सबूत मेरे परीक्षण कार्यक्रम का आउटपुट है: '01-26 20: 28: 43.675: ई/[एलएमआई-नेटिव] (9 280): लेन: 7, जचर: 2, wchar: 4' – Kobor42

+2

@ Kobor42 - आपका परीक्षण कार्यक्रम क्या करता है? क्या आप कह रहे हैं कि आपको एक उदाहरण मिला जहां wchar_t 4 बाइट था? मुझे वास्तव में इसका एहसास नहीं हुआ था, लेकिन यह फ़ंक्शन विंडोज़ पर चलाने के लिए डिज़ाइन किया गया था, जहां wchar_t हमेशा होता है 2. अब मुझे एहसास है कि wchar_t संकलक विशिष्ट है और आपके प्लेटफ़ॉर्म पर अलग हो सकता है। – Benj

+0

बिल्कुल। एंड्रॉइड पर पहले 2.1 wchar_t 1 बाइट है। 2.1 और बाद में 4 बाइट्स है। – Kobor42

4

और कौन wsz frees? मैं एसटीएल की सिफारिश करता हूं!

std::wstring JavaToWSZ(JNIEnv* env, jstring string) 
{ 
    std::wstring value; 
    if (string == NULL) { 
     return value; // empty string 
    } 
    const jchar* raw = env->GetStringChars(string, NULL); 
    if (raw != NULL) { 
     jsize len = env->GetStringLength(string); 
     value.assign(raw, len); 
     env->ReleaseStringChars(string, raw); 
    } 
    return value; 
} 
+0

सी ++ 11 का उपयोग करते समय एक अच्छा समाधान नहीं है क्योंकि wstring मूल्य से वापस किया जाएगा। (जाहिर है सी ++ 11 पोस्ट करें यह निर्माण किया जाएगा जो कुशल होगा) – Benj

+4

value.assign (कच्चे, लेन); मान्य नहीं है। मुझे लगता है कि यह मूल्य होना चाहिए। असाइन (कच्चे, कच्चे + लेन); लेकिन मैंने अभी तक परीक्षण नहीं किया है। – mjaggard

+0

ग्रेट - मेरे लिए पूरी तरह से सी # -> सी ++/सीएलआई -> जेएनआई -> जावा एप्लिकेशन में काम किया! – bbqchickenrobot

0

बल्कि सरल।

std::wstring Java_To_WStr(JNIEnv *env, jstring string) 
{ 
    std::wstring value; 

    const jchar *raw = env->GetStringChars(string, 0); 
    jsize len = env->GetStringLength(string); 
    const jchar *temp = raw; 
    while (len > 0) 
    { 
     value += *(temp++); 
     len--; 
    } 
    env->ReleaseStringChars(string, raw); 

    return value; 
} 

एक बेहतर समाधान हो सकता है (धन्यवाद के लिए: लेकिन ReleaseStringChars

JNIEXPORT jboolean JNICALL Java_TestClass_test(JNIEnv * env, jobject, jstring string) 
{ 
    const wchar_t * utf16 = (wchar_t *)env->GetStringChars(string, NULL); 
    ... 
    env->ReleaseStringChars(string, utf16); 
} 
13

इस कोई मदद करता है, तो द्वारा स्मृति को मुक्त करने के लिए मत भूलना ... मैं एक Android परियोजना के लिए इस समारोह का उपयोग किया है फीडबैक):

std::wstring Java_To_WStr(JNIEnv *env, jstring string) 
{ 
    std::wstring value; 

    const jchar *raw = env->GetStringChars(string, 0); 
    jsize len = env->GetStringLength(string); 

    value.assign(raw, raw + len); 

    env->ReleaseStringChars(string, raw); 

    return value; 
} 
+0

नीट, हालांकि मुझे लगता है कि एक बार में एक बफर के साथ wstring लोड करने पर संदेह होगा कि एक समय में एक चरित्र अधिक कुशल होगा। – Rup

+0

हाँ, मुझे ऐसा भी लगता है। मैंने अभी अपना जवाब अपडेट कर दिया है :) – gergonzalez

+0

क्या सी ++ कंपाइलर नोटिस करता है कि आप एक स्वचालित लौट रहे हैं, और इसे ढेर पर आवंटित करते हैं, न कि ढेर पर? –