2010년 11월 28일 일요일

한글완성형(EUC-KR)을 iPhone/Mac에서 사용할 수 있는 언어셋으로 변환하기



Windows PC로부터 받아온 문자열 데이터를 사용하기 위해 NSString으로 변환하니 문자가 깨져버렸다. 이유를 찾아보니, Encoding이 맞지 않아서였다.

그래서 위해 개발자 문서에 나온 모든 Encoding 타입을 적용하였지만, 원하는 결과가 나오지 않았다. 

Apple에서 iPhone에는 제공하지 않는 것일까?

그래서 MAC Application을 간단히 만들어 테스트 해보았다.
MAC OS에서는 [NSString stringWithFormat:@"%s", anyString];
위와 같이 처리하면 자동으로 변환이 되었다. 하지만 유독 iPhone에서만 안되는 것일까?

처리 방법은 아래 레퍼런스를 참고하면 된다.
한글, 중국어, 일본어 등 여러 2bytes 문자들에 대해서 정의해놓은 encoding이다.
  
한글의 경우, 0x80000003으로 정의되어 있는 것을 알 수 있다. 즉, 
[NSString stringWithCString:anyString encoding:0x80000003]; 
과 같이 처리하면 원하는 결과를 얻을 수 있다.

실제 접했던 문제에 대한 예를 들어 설명해보자.
 Windows PC에서 수신 데이터의 메모리 값이 다음과 같았다.
0xBF 0xC0 0xC8 0xC4
이 데이터는 한글로 '오후'이다.
해당 데이터를 잘라낸 다음 버퍼에 넣고, 그 뒤로 0x00 널문자를 2바이트 추가 한다.
그리고 위의 방법과 같이 0x80000003 Encoding을 사용하면 원하는 결과를 얻을 수 있다.
 <출처 : OSXDEV Forum>

NSString의 인코딩

NSString은 내부적으로 모두 유니코드로 저장된다. 하지만, NSString에 문자열을 넣거나 뺄때 유니코드가 아닌 다른 인코딩을 사용할 수 있다.
NSString이 기본적으로 지원하는 인코딩은 NSString.h에 다음과 같이 선언되어 있다.
typedef unsigned NSStringEncoding;

enum {
    NSASCIIStringEncoding = 1,  /* 0..127 only */
    NSNEXTSTEPStringEncoding = 2,
    NSJapaneseEUCStringEncoding = 3,
    NSUTF8StringEncoding = 4,
    NSISOLatin1StringEncoding = 5,
    NSSymbolStringEncoding = 6,
    NSNonLossyASCIIStringEncoding = 7,
    NSShiftJISStringEncoding = 8,
    NSISOLatin2StringEncoding = 9,
    NSUnicodeStringEncoding = 10,
    NSWindowsCP1251StringEncoding = 11,    /* Cyrillic; same as AdobeStandardCyrillic */
    NSWindowsCP1252StringEncoding = 12,    /* WinLatin1 */
    NSWindowsCP1253StringEncoding = 13,    /* Greek */
    NSWindowsCP1254StringEncoding = 14,    /* Turkish */
    NSWindowsCP1250StringEncoding = 15,    /* WinLatin2 */
    NSISO2022JPStringEncoding = 21,         /* ISO 2022 Japanese encoding for e-mail */
    NSMacOSRomanStringEncoding = 30,

    NSProprietaryStringEncoding = 65536    /* Installation-specific encoding */
};
하지만, NSString은 실제로 Mac OS에서 사용할 수 있는 모든 인코딩을 지원한다.

다음은 NSString클래스의 인코딩관련 메쏘드들이다.
/* 사용자 기본 인코딩을 구한다 */
+ (NSStringEncoding)defaultCStringEncoding;

/* NSString에서 사용가능한 모든 인코딩을 구한다 */
+ (const NSStringEncoding *)availableStringEncodings;

/* 인코딩의 이름을 구한다 */
+ (NSString *)localizedNameOfStringEncoding:(NSStringEncoding)encoding;

/* 현재 스트링을 변환시 가장 빠르거나 메모리가 적게 드는 인코딩을 구한다 */
- (NSStringEncoding)fastestEncoding;
- (NSStringEncoding)smallestEncoding;

/* 데이터의 손실없이 해당 인코딩으로 변환 가능한지 여부를 알아본다 */
- (BOOL)canBeConvertedToEncoding:(NSStringEncoding)encoding;

/* 해당 인코딩의 데이터로부터 NSString을 생성한다 */
- (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding;

/* 현재 스트링을 해당 인코딩의 데이터로 변환하여 얻는다 */
- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding allowLossyConversion:(BOOL)lossy;
- (NSData *)dataUsingEncoding:(NSStringEncoding)encoding; /* lossy=NO */
다음의 코드를 사용해서 NSString에서 지원하는 모든 인코딩의 이름과 그 값을 알 수 있다.
NSStringEncoding *encoding = [NSString availableStringEncodings];
while (*encoding) {
    NSLog(@"%@ %x", [NSString localizedNameOfStringEncoding:*encoding], *encoding);
    encoding++;
}
다음은 NSString에서 지원하는 인코딩들이다.
Western (Mac OS Roman)0x1e3030
Japanese (Mac OS)0x800000012147483649-2147483647
Traditional Chinese (Mac OS)0x800000022147483650-2147483646
Korean (Mac OS)0x800000032147483651-2147483645
Arabic (Mac OS)0x800000042147483652-2147483644
Hebrew (Mac OS)0x800000052147483653-2147483643
Greek (Mac OS)0x800000062147483654-2147483642
Cyrillic (Mac OS)0x800000072147483655-2147483641
Devanagari (Mac OS)0x800000092147483657-2147483639
Gurmukhi (Mac OS)0x8000000a2147483658-2147483638
Gujarati (Mac OS)0x8000000b2147483659-2147483637
Thai (Mac OS)0x800000152147483669-2147483627
Simplified Chinese (Mac OS)0x800000192147483673-2147483623
Tibetan (Mac OS)0x8000001a2147483674-2147483622
Central European (Mac OS)0x8000001d2147483677-2147483619
Symbol (Mac OS)0x666
Dingbats (Mac OS)0x800000222147483682-2147483614
Turkish (Mac OS)0x800000232147483683-2147483613
Croatian (Mac OS)0x800000242147483684-2147483612
Icelandic (Mac OS)0x800000252147483685-2147483611
Romanian (Mac OS)0x800000262147483686-2147483610
Keyboard Symbols (Mac OS)0x800000292147483689-2147483607
Farsi (Mac OS)0x8000008c2147483788-2147483508
Cyrillic (Mac OS Ukrainian)0x800000982147483800-2147483496
Western (Mac VT100)0x800000fc2147483900-2147483396
Unicode™ (UTF-16)0xa1010
Unicode™ (UTF-8)0x444
Western (ISO Latin 1)0x555
Central European (ISO Latin 2)0x999
Western (ISO Latin 3)0x800002032147484163-2147483133
Central European (ISO Latin 4)0x800002042147484164-2147483132
Cyrillic (ISO 8859-5)0x800002052147484165-2147483131
Arabic (ISO 8859-6)0x800002062147484166-2147483130
Greek (ISO 8859-7)0x800002072147484167-2147483129
Hebrew (ISO 8859-8)0x800002082147484168-2147483128
Turkish (ISO Latin 5)0x800002092147484169-2147483127
Nordic (ISO Latin 6)0x8000020a2147484170-2147483126
Thai (ISO 8859-11)0x8000020b2147484171-2147483125
Baltic Rim (ISO Latin 7)0x8000020d2147484173-2147483123
Celtic (ISO Latin 8)0x8000020e2147484174-2147483122
Western (ISO Latin 9)0x8000020f2147484175-2147483121
Latin-US (DOS)0x800004002147484672-2147482624
Greek (DOS)0x800004052147484677-2147482619
Baltic Rim (DOS)0x800004062147484678-2147482618
Western (DOS Latin 1)0x800004102147484688-2147482608
Central European (DOS Latin 2)0x800004122147484690-2147482606
Turkish (DOS)0x800004142147484692-2147482604
Icelandic (DOS)0x800004162147484694-2147482602
Arabic (DOS)0x800004192147484697-2147482599
Cyrillic (DOS)0x8000041b2147484699-2147482597
Thai (Windows, DOS)0x8000041d2147484701-2147482595
Japanese (Windows, DOS)0x888
Simplified Chinese (Windows, DOS)0x800004212147484705-2147482591
Korean (Windows, DOS)0x800004222147484706-2147482590
Traditional Chinese (Windows, DOS)0x800004232147484707-2147482589
Western (Windows Latin 1)0xc1212
Central European (Windows Latin 2)0xf1515
Cyrillic (Windows)0xb1111
Greek (Windows)0xd1313
Turkish (Windows Latin 5)0xe1414
Hebrew (Windows)0x800005052147484933-2147482363
Arabic (Windows)0x800005062147484934-2147482362
Baltic Rim (Windows)0x800005072147484935-2147482361
Vietnamese (Windows)0x800005082147484936-2147482360
Western (ASCII)0x111
Japanese (Shift JIS X0213)0x800006282147485224-2147482072
Chinese (GBK)0x800006312147485233-2147482063
Chinese (GB 18030)0x800006322147485234-2147482062
Japanese (ISO 2022-JP)0x152121
Korean (ISO 2022-KR)0x800008402147485760-2147481536
Japanese (EUC)0x333
Simplified Chinese (EUC)0x800009302147486000-2147481296
Traditional Chinese (EUC)0x800009312147486001-2147481295
Korean (EUC)0x800009402147486016-2147481280
Japanese (Shift JIS)0x80000a012147486209-2147481087
Cyrillic (KOI8-R)0x80000a022147486210-2147481086
Traditional Chinese (Big 5)0x80000a032147486211-2147481085
Western (Mac Mail)0x80000a042147486212-2147481084
Traditional Chinese (Big 5 HKSCS)0x80000a062147486214-2147481082
Western (NextStep)0x222
Non-lossy ASCII0x777
Western (EBCDIC US)0x80000c022147486722-2147480574
표에서 알 수 있듯이 NSString.h에서 선언되어 있지 않은 인코딩은 CFString의 인코딩 번호에 0x80000000를 더한 값이다.

댓글 없음:

댓글 쓰기