[언리얼] 언리얼 문자열 처리 방식
Table of Contents
UTF-16에 대해 알아보자 #
- 문자열 처리방식은 ANSI, ASCII, EUC-KR, CP949, UTF-8 BOM, UTF-8, UTF-16 등 정말 다양하다.
- 유니코드(Unicode)
- 전 세계의 모든 문자를 컴퓨터에서 일관되게 표현할 수 있도록 고안된 코드 집합(표)이다.
- 인코딩 방식이란?
- 문자나 기호들을 컴퓨터가 이용할 수 있는 신호로 만드는 것을 말한다.
- 즉, 문자들을 바이트열에 표현하는 방식이다.
- 유니코드의 인코딩 방식
- 여기에는 UTF-8, UTF-16 등이 있다.
- ANSI, ASCII, EUC-KR, CP949 등의 인코딩 방식은 코드 표에서 원하는 문자에 해당하는 코드를 찾아 그대로 바이트열에 쓰는 방식이었다.
- 하지만 유니코드는 똑같은 문자도 인코딩 방식에 따라 바이트열에 다르게 표현될 수 있다.
- 먼저 유니코드 표에서 인코딩하고자 하는 문자의 코드를 찾는다.
- 다음으로, 그 코드를 각 인코딩 방식에서 정해둔 어떤 규칙에 따라 변형시켜서 바이트열에 표현한다.
- UTF-16 (16-bit Unicode Transformation Format)
- 인코딩 하려는 문자가 속한 범위에 따라서 16bit 단위로 늘려가며 인코딩하는 가변 인코딩 방식이다.
- 주로 사용되는 기본 다국어 평면 (BMP, Basic multilingual plane)에 속하는 문자들은 그대로 16bit 값으로 인코딩이 되고, 그 이상의 문자는 특별히 정해진 방식으로 32bit로 인코딩이 된다.
- BOM(Byte Order Mark, 바이트 순서 표시)
- 파일의 맨 앞에 붙여서, 바이트를 저장한 방식이 리틀 엔디언인지 빅 엔디언인지 전달한다.
- 리틀 엔디언(Little Endian) 과 빅 엔디언(Big Endian)
- 컴퓨터는 데이터를 byte 단위로 나눠서 메모리에 저장하는데, 이 때 데이터를 메모리에 어떤 순서로 저장할 것인가(바이트 오더)를 엔디안이라고 한다.
항목 설명 0x12345678의 표현리틀 엔디언 낮은 주소에 MSB부터 저장하는 방식이다.
(Most Significant Bit, 최상위 비트)0x12,0x34,0x56,0x78빅 엔디언 낮은 주소에 LSB부터 저장하는 방식이다.
(Least Significant Bit, 최하위 비트)0x78,0x56,0x34,0x12
- 컴퓨터는 데이터를 byte 단위로 나눠서 메모리에 저장하는데, 이 때 데이터를 메모리에 어떤 순서로 저장할 것인가(바이트 오더)를 엔디안이라고 한다.
언리얼의 문자열 처리 방식 #
- 언리얼은 문자열 처리방식을 통일하여 UTF-16을 사용한다.
- 동아시아(한국어 포함) 인코딩의 경우 UTF-8 방식으로 저장해야 한다.
- 언리얼 공식 문서 : 캐릭터 인코딩
- 인코딩 변환 매크로들
- 스트링을 다양한 인코딩으로 상호 변환할 수 있는 매크로가 많이 있다.
TCHAR_TO_ANSI(str)
TCHAR_TO_OEM(str)
ANSI_TO_TCHAR(str)
TCHAR_TO_UTF8(str)
UTF8_TO_TCHAR(str)
- 유니코드를 위한 언리얼 표준 캐릭터 타입(네이티브 유니코드 인코딩)이 바로
TCHAR이다. TEXT()매크로를 사용해서 문자열을 지정하면TCHAR[]배열로 지정된다.TEXT()매크로를 지정하지 않으면, 리터럴은 ANSI 를 사용해서 인코딩되기에, 지원되는 글자가 크게 제한된다.- ANSI 리터럴을
FString로 전달하면TCHAR으로의 변환하는 과정을 겪어야 하기에,TEXT()를 사용하는 편이 보다 효율적이다.
- ANSI 리터럴을
- 언리얼 공식 문서 : 문자열 처리
FString #
- 조작이 가능한 유일한 스트링 클래스이다.
TCHAR[]배열로 만들어져있다.
FString과TCHAR와의 관계
// TCHAR 배열
TCHAR LogCharArray[] = TEXT("Hello Unreal");
UE_LOG(LogTemp, Log, LogCharArray);
// TCHAR 배열을 다루는 FString 클래스 -> *연산자 붙여야 한다.
FString LogCharString = LogCharArray;
UE_LOG(LogTemp, Log, TEXT("%s"), *LogCharString);
// FString 클래스에 *연산자를 붙이면 const TCHAR*를 받을 수 있다.
const TCHAR* LogCharPtr = *LogCharString;
// FString 클래스 안에 있는 진짜 데이터를 끄집어내는 방법 -> 문자열 수정 가능
TCHAR* LogCharDataPtr = LogCharString.GetCharArray().GetData();
- 다른 타입과
FString간의 변환
int32 IntValue = 32;
float FloatValue = 3.141592;
// Int, Float -> FString
FString FloatIntString = FString::Printf(TEXT("Int : %d, Float : %f"), IntValue, FloatValue);
FString IntString = FString::FromInt(IntValue);
FString FloatString = FString::SanitizeFloat(FloatValue);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString);
UE_LOG(LogTemp, Log, TEXT("Int : %s, Float : %s"), *IntString, *FloatString);
// FString -> Int, Float (안전하지 않으므로 주의가 필요하다.)
int32 IntValueFromString = FCString::Atoi(*IntString);
float FloatValueFromString = FCString::Atof(*FloatString);
FString FloatIntString2 = FString::Printf(TEXT("Int : %d, Float : %f"), IntValueFromString, FloatValueFromString);
UE_LOG(LogTemp, Log, TEXT("%s"), *FloatIntString2);
FString은 용도에 따라FName,FText로 관리될 수 있다.
FName #
- 에셋 관리를 위해 사용되는 문자열 체계이다. 문자를 표현하는 용도가 아닌 에셋 키를 지정하는 용도로 사용한다.
- 대소문자를 구분하지 않고, 한 번 선언되면 변경이 불가능하다.
FNamePool이라는 싱글톤 자료구조가 있고, 그 안에서FName을 해시 테이블로 관리한다.- 해시를 사용하므로 찾기가 매우 빠르다.
FName을 생성할 때는 문자열을 Key로 변환하고 전역 Pool에 있는지를 검사하는 오버헤드가 발생하므로 주의가 필요하다.
// 빈번하게 호출되는 상황
for (int i = 0; i < 10000; i++)
{
// FName 생성자에 문자열을 넣으면?
// 문자열을 Key로 변환하고 전역 Pool에 있는지를 검사하는 오버헤드가 발생한다.
// 따라서 주의가 필요하다.
FName SearchInNamePool = FName(TEXT("pelvis"));
// 이렇게 한번만 처리하도록 하는 것이 좋겠다.
const static FName StaticOnlyOnce(TEXT("pelvis"));
}
FText #
- 다국어 지원을 위한 문자열 체계이다.
- 별도의 문자열 테이블 정보가 추가로 요구된다.
- 게임 빌드시 자동으로 다양한 국가별 언어로 변환된다.
상호 간의 변환 #
FString으로의 변환
| from | to | 코드 |
|---|---|---|
FName |
FString |
MyName.ToString(); |
FText |
FString |
MyText.ToString(); 언어 변환시 손실 위험 때문에 안전하지 않다. |
FName으로의 변환
| from | to | 코드 |
|---|---|---|
FString |
FName |
FName(*MyString); FName이 대소문자 구분 없기에 손실 위험이 있다. |
FText |
FName |
FText → FString → FName (직접 변환 없음)FName이 대소문자 구분 없기에 손실 위험이 있다. |
FText으로의 변환
| from | to | 코드 |
|---|---|---|
FString |
FText |
FText::FromString(MyString); 자동 현지화 못받을 수 있다. |
FName |
FText |
FText::FromName(MyName); 자동 현지화 못받을 수 있다. |