Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- SWT
- 자바
- 이지형
- 러시아
- "명탐정 코난"
- 민동현의토요명화
- EV-DO Rev. B
- itmusic
- 유희열의라디오천국
- 라디오
- brew
- 퀄컴
- 차트쇼쇼쇼
- Java
- 김장훈의who
- 그녀가말했다
- VoIP
- 한국의 기획자들
- CDMA
- 민동현
- 김장훈
- 모던음악만만세
- 위피
- ETF
- 사요
- Wibro
- USIM
- HSDPA
- 페이스북
- 공정위
Archives
- Today
- Total
02-05 00:07
zyint's blog
한글 문자열 깨짐 문제 본문
요약
자바 JNI를 통해서 문자열을 jstring 타입으로 넘길 경우 2 바이트를 사용하는 유니코드 등의 한글과 같은 문자는 깨짐 현상이 발생하게 된다. 여기에서는 이러한 글자 깨짐 현상을 해결하고자 한다.
소스코드 다운로드
주의할 점
Java쪽에서 넘겨 받은 문자열을 "jstring string" 변수에 저장하였을 때 C언어에서 사용할 수 있는 문자열로 가공하려면,
- char * cString;
/* 최종 C 문자열을 가리킬 포인터 */
jbyteArray jba;
jba = javaGetBytes(env, string);
cString = jbyteArray2cstr(env, jba);
/* cString 이 C어언에서 사용할 수 있는 문자열이다. 이것을 사용한 후에 필히 메모리를 free해줘야만 한다.
그렇지 않으면 메모리 누수로 어플리케이션이 죽는다. */
free(cString);
보시다시피 Java 문자열에서 C 문자열로 변환한 뒤에 필히 메모리를 free해야만 한다.
소스코드
NativeStringUtil.h
- #ifndef _Included_NativeStringUtil
#define _Included_NativeStringUtil
#ifdef __cplusplus
extern "C" {
#endif
char *jbyteArray2cstr( JNIEnv *env, jbyteArray javaBytes );
jbyteArray cstr2jbyteArray( JNIEnv *env, const char *nativeStr);
jbyteArray javaGetBytes( JNIEnv *env, jstring str );
jbyteArray javaGetBytesEncoding( JNIEnv *env, jstring str, const char *encoding );
jstring javaNewString( JNIEnv *env, jbyteArray javaBytes );
jstring javaNewStringEncoding(
JNIEnv *env, jbyteArray javaBytes, const char *encoding );
#ifdef __cplusplus
}
#endif
#endif
NativeStringUtil.c
- /*
* @(#)NativeStringUtil.c 1.0 98/01/02 Deogtae Kim (dtkim@calab.kaist.ac.kr)
*/
#include <stdlib.h>
#include <string.h>
#include <jni.h>
#include "NativeStringUtil.h"
/* 효율성을 높이기 위한 캐슁 변수 */
static jclass class_String;
static jmethodID mid_getBytes, mid_getBytesEncoding;
static jmethodID mid_newString, mid_newStringEncoding; - /* 자바 바이트 배열로부터 C 문자열을 생성하여 반환
*/
char *jbyteArray2cstr( JNIEnv *env, jbyteArray javaBytes )
{
size_t len = (*env)->GetArrayLength(env, javaBytes);
jbyte *nativeBytes = (*env)->GetByteArrayElements(env, javaBytes, 0);
char *nativeStr = malloc(len+1);
strncpy( nativeStr, nativeBytes, len );
nativeStr[len] = '\0';
(*env)->ReleaseByteArrayElements(
env, javaBytes, nativeBytes, JNI_ABORT);
return nativeStr; /* ML(Memory Loss 발생 */
}
/* C 문자열로부터 자바 바이트 배열을 생성하여 반환
*/
jbyteArray cstr2jbyteArray( JNIEnv *env, const char *nativeStr)
{
jbyteArray javaBytes;
int len = strlen( nativeStr );
javaBytes = (*env)->NewByteArray(env, len);
(*env)->SetByteArrayRegion(
env, javaBytes, 0, len, (jbyte *) nativeStr );
return javaBytes;
} - /* 자바 스트링을 디폴트 인코딩의 자바 바이트 배열로 변환.
* String 클래스의 getBytes() 메쏘드를 호출한다.
*/
jbyteArray javaGetBytes( JNIEnv *env, jstring str )
{
if ( mid_getBytes == 0 )
{ if ( class_String == 0 )
{ jclass cls = (*env)->FindClass(env, "java/lang/String");
if ( cls == 0 )
return 0; /* 오류 */
class_String = (*env)->NewGlobalRef(env, cls);
if ( class_String == 0 )
return 0; /* 오류 */
}
mid_getBytes = (*env)->GetMethodID(
env, class_String, "getBytes", "()[B");
if (mid_getBytes == 0)
return 0;
}
/* str.getBytes(); */
return (*env)->CallObjectMethod( env, str, mid_getBytes );
} - /* 자바 스트링을 지정된 인코딩 `encoding'의 자바 바이트 배열로 변환.
* String 클래스의 getBytes(String encoding) 메쏘드를 호출한다.
*/
jbyteArray javaGetBytesEncoding( JNIEnv *env, jstring str, const char *encoding )
{
if ( mid_getBytesEncoding == 0 )
{ if ( class_String == 0 )
{ jclass cls = (*env)->FindClass(env, "java/lang/String");
if ( cls == 0 )
return 0; /* 오류 */
class_String = (*env)->NewGlobalRef(env, cls);
if ( class_String == 0 )
return 0; /* 오류 */
}
mid_getBytesEncoding = (*env)->GetMethodID(
env, class_String, "getBytes", "(Ljava/lang/String;)[B");
if (mid_getBytesEncoding == 0)
return 0;
}
/* str.getBytes( encoding ); */
return (*env)->CallObjectMethod(
env, str, mid_getBytesEncoding, (*env)->NewStringUTF(env, encoding));
} - /* 디폴트 인코딩의 자바 바이트 배열을 자바 스트링으로 변환.
* String 클래스의 new String(byte[] bytes) 메쏘드를 호출한다.
*/
jstring javaNewString( JNIEnv *env, jbyteArray javaBytes )
{
if ( mid_newString == 0 )
{ if ( class_String == 0 )
{ jclass cls = (*env)->FindClass(env, "java/lang/String");
if ( cls == 0 )
return 0; /* 오류 */
class_String = (*env)->NewGlobalRef(env, cls);
if ( class_String == 0 )
return 0; /* 오류 */
}
mid_newString = (*env)->GetMethodID(
env, class_String, "<init>", "([B)V");
if ( mid_newString == 0 )
return 0;
}
/* new String( javaBytes ); */
return (*env)->NewObject(
env, class_String, mid_newString, javaBytes );
} - /* 지정된 인코딩 `encoding'의 자바 바이트 배열을 자바 스트링으로 변환.
* String 클래스의 new String(byte[] bytes, String encoding)
* 메쏘드를 호출한다.
*/
jstring javaNewStringEncoding(
JNIEnv *env, jbyteArray javaBytes, const char *encoding )
{
// int len;
jstring str;
if ( mid_newString == 0 )
{ if ( class_String == 0 )
{ jclass cls = (*env)->FindClass(env, "java/lang/String");
if ( cls == 0 )
return 0; /* 오류 */
class_String = (*env)->NewGlobalRef(env, cls);
if ( class_String == 0 )
return 0; /* 오류 */
}
mid_newString = (*env)->GetMethodID(
env, class_String, "<init>", "([BLjava/lang/String;)V");
if ( mid_newString == 0 )
return 0;
}
/* new String( javaBytes, encoding ); */
str = (*env)->NewObject(
env, class_String, mid_newString, javaBytes,
(*env)->NewStringUTF(env, encoding) );
return str;
}
출처
http://blog.naver.com/mismir?Redirect=Log&logNo=40011464831
이 글은 스프링노트에서 작성되었습니다.
Comments