최근 유니코드를 기본 문자셋으로 사용하는 개발 환경이 많아졌다.

최근이라고 할수도 없이 java 와 C# 이 대표적이다

 

유니코드 문자셋이 글로벌환경에서는 매우 유용하게 사용할 수 있으나

특정 상황에서는 매우 껄끄러운 경우가 발생한다.

문자로만 처리되는 환경에서 더욱 그러하다.

멀티바이트 문자셋(EUC-KR 같은) 을 사용하는 환경에서는 문자열의 길이 = 화면에 표시되는 길이 이지만

(고정폭 문자열인경우에 한해서 이지만 대체적으로 1:1 비율을 유지한다.)

유니코드 환경에서는 문자열 길이 = 화면에 표시되는 길이 라고 볼수가 없다.

한글이나 중국어, 일본어 모두 1문자는 실제로 몇바이트를 차지하느냐와 관계없이

문자형(char) 1개 변수로 처리되기 때문이다.

 

이때문에 문자가 출력되는 길이를 맞추려고 할때 과거 프로그램과 차이가 발생할수 밖에 없다.

어떤 사람은 단순히 BYTE 길이로 자르도록 처리를 헀는데

그런식으로 처리를 하게 되는 경우 "가나다" 를 5 자리로 자른다 라고 했을 경우에

 

byte[] buf = System.Text.Encoding.Default.GetBytes( "가나다" );

string str = System.Text.Encoding.Default.GetString( buf, 0, 5 );

 

라고 하는 경우가 있는데 이런경우 결과값은 "가나?" 가 된다.

바이트 단위로 5 바이트 를 잘랐기 때문에 마지막 "다" 의 2 바이트중 첫번째 바이트만 가져왔고

시스템에서 해석할수 없는 문자이기 때문에 "?" 로 처리 되는것이다.

이는 문자 처리에 대한 지식이 부족했거나 방법만 제시하고 테스트를 해보지 않은것으로 보인다.

 

아래는 이를 보완하기 위해 추가한 함수이다. 

//문자열을 특정 길이로 변환하고 남는 부분은 공백문자로 채운다
private string SubStringWithPad(string str, int len)
{
	// ANSI 멀티바이트 문자열로 변환 하여 길이를 구한다.
	int inCnt = Encoding.Default.GetByteCount(str);
	if (inCnt > len)
	{
		int i = 0;
		for (i = str.Length - 1; inCnt > len; i--)
		{
			//ANSI 문자는 1, 이외의 문자는 2자리로 계산한다
			if (str[i] > 0x7f)
			{
				inCnt -= 2;
			}
			else
			{
				inCnt -= 1;
			} 
		}
		// i는 마지막 문자 인덱스이고 substring 의 두번째 파라미터는 길이이기 때문에 + 1 한다.
		str = str.Substring(0, i + 1);
		// ANSI 멀티바이트 문자열로 변환 하여 길이를 구한다.
		inCnt = Encoding.Default.GetByteCount(str);
	}
	//PadRight(len) 이 맞겠지만 유니코드 처리가 되기 때문에 멀티바이트 문자도 1로
	//처리되어 길이가 일정하지 않기 때문에 아래와 같이 계산하여 Padding한다
	str = str.PadRight(str.Length + len - inCnt);
	return str;
} 

 

반복문 없이 처리할 수 있는 방법 딱히 떠오르지 않아 반복문을 통해 처리하도록 하였다.

뒤에서 빼는 방법이나 앞에서 더하는 방법이나 별 차이는 없어보인다.

mfc 에서는 _tcsinc 를 이용해서 앞에서부터 처리하는 방법이 있지만

c#에서는 어떤 방법이 있을지 좀더 찾아보아야 할것 같다.

Posted by 동적할당
: