336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

이번에, php 로 만든 소스를 asp 로 바꾸면서 몇가지 특이한 점을 배우게 되었다.
알면서도 잊고 지나치는 부분으로, 바이트 단위로 조작하느냐 아니느냐 하는 문제이다.

아다시피, php 는 C 의 문법을 따르고 있고 비슷한 함수들이 많기에, 문자열을 조작함에 있어서도 C 와 마찬가지로 바이트 단위로 조작한다. 그러다보니, 한글을 다루다보면, 한글이 깨지는 경우가 발생하는데, 이는 바이트 단위로 쪼개는 과정에서 발생한다.

우선, php 의 함수를 이용한 경우를 보자.

strlen("a") = 1
strlen("ㄱ") = 2

이다.
즉, 한글이면, 자음이던 모음이던 상관없이 2배의 길이를 가진다. 그것은, 문자 하나가 0 과 1 로 구성된 8개의 비트로 이루어지는데, 한글의 경우에는 16비트로 이루어지기 때문이다. 따라서, php 에서 다루는 함수인 ord(), chr(), strlen() 은 모두 8비트 단위로 쪼개서 계산하는 것이다.

반면, asp 의 경우에는 좀 다르다. 가장 기본적으로 널리 쓰이는 함수들인 asc(), chr(), mid(), len() 함수들은 모두 문자단위를 기준으로 체크된다. 즉,

len("a") = 1
len("ㄱ") = 1

이라는 차이점이 있다. 즉, 한글이건 영어,숫자이건 간에, 인간이 인지하는 문자 1개를 기준으로 길이값을 반환하는 것이다. 그래서, 한글관련 문자열을 다루는데 굉장히 편하다. 반면, php 에는 이런 함수들이 없기 때문에, 만약, asp 의 이런 함수들과 같은 기능을 하게 하려면 직접 함수를 만들어야 한다.

그런데, 이번에 문제가 된것은, 오히려 비트단위로 다뤄져야할 한글이 문자 단위로 다루어지는 바람에 발생했다. 즉, ascB(), chrB(), midB(), lenB() 같은 함수를 사용하지 않던 나로서는, php 코드를 asp 로 바꾸면서 이런 부분을 전혀 예측하지 못하고 있었던 것이다.

따라서, php 의 코딩 부분에서 만약 ord(), chr(), strlen() 같은 것들이 쓰였다면, 한글을 조작할 경우를 감안해서 asp 코드로 바꿀때는 바이트 단위로 계산하는 ascB(), chrB(), midB(), lenB() 같은 함수들을 적절히 이용해야 하는 것이다. 이 함수들은 php 의 기본함수들과 마찬가지로 문자열을 바이트 단위로 쪼개어서 계산하는 함수들이다.

ascB() 는, 주어진 문자열을 바이트 단위로 쪼개어서 8비트(1바이트) 기준으로 아스키 코드값을 출력해준다. 만약, 한글을 넣는다면 전혀 예측하지 못한 결과가 나올수 있다. 이것은 8비트에 대해서만 결과를 리턴하기 때문에, 한글을 넣으면 전체 2바이트중 앞쪽의 1바이트에 대한 결과만을 리턴하기 때문이다.

아래의 코드를 비교해보면, 그 차이를 잘 알 수 있다.

<%
Response.Write ascB("ㄱ") '49

test = "ㄱ"
Response.Write ascB(midB(test,1,1))  '49
Response.Write ascB(midB(test,2,1))  '49
%>

코드에서 보듯이, 단순히 한글에 대해서 ascB() 를 실행하면, 한가지 코드만 나온다. 그러나, 그 아래의 코드에서 보듯이, 이를 바이트 단위로 두개로 쪼개서 출력시키면, 49 라는 값이 두번 나온다. 즉, 한글 'ㄱ' 은 아스키 코드 49 가 두개 모여서 이루어진 문자이다. 한글을 쪼개기 위해서 midB() 를 사용하였다.

이와 마찬가지로, chrB() 도 같은 방식으로 쪼개어서 사용할 수 있다.

재미있는것은, 이렇게 쪼개어진 1바이트를 그대로 출력하면 한글이 깨지지만, 쪼개진 두개의 바이트를 연달아 출력하면 한글이 조합되어 브라우저에 출력된다. 즉,

<%
Response.write chrB(49)
%>

만 한다면, 한글이 제대로 출력되지 않고 1 이라는 값이 출력되지만,

<%
Response.write chrB(49)&chrB(49)
%>

라고 처리하면, 한글인 'ㄱ' 이 출력된다. 다음은, php 의 ord(), strlen() 을 사용한 코드를 asp 로 옮길때의 모습이다. 우선, php 에서, 지정한 문자열을 strlen() 으로 쪼개고, ord() 로 변환하였다가, chr() 로 되돌리는 코딩이 있다고 하자. 코드는 아래와 같다.

<?
$test = "123가나다abc";
echo $test;
echo "<br>";
$leng = strlen($test);
for($i=0;$i<$leng;$i++)
{
  $n = substr($test,$i,1);
 $rslt .= ord($n)."/";  //출력: 49/50/51/176/161/179/170/180/217/97/98/99/
}
echo $rslt;
echo "<br>";
$m = explode("/",$rslt);   //13
$mleng = count($m);
echo $mleng;
echo "<br>";

for($i=0;$i<$mleng;$i++)
{
  $th .= chr($m[$i]);
}
echo $th;  //출력결과: 123가나다abc
?>

이 코드를 asp 코드로 바꾼다면, 한글이 섞인 문자열이기 때문에 len() 이나 mid(), asc(), chr() 을 사용하면 안된다. 그럴경우, 한글이 깨지게 된다.(한글 문자 부분에서 앞의 8비트만 인식하기 때문) 따라서, asp 로 바꿀때는 midB(), ascB(), chrB(), midB() 등을 이용해야 한글까지 모두 에러없이 변환할 수 있다.

<%
test = "123가나다abc"
Response.Write test & "<br>"
leng = lenB(test)
for i=1 to leng-1
  n = midB(test,i,1)
  rslt = rslt & ascB(n) & "/"
next
'출력결과비교:
'php: 49/50/51/176/161/179/170/180/217/97/98/99/
'asp: 49/0/50/0/51/0/0/172/152/176/228/178/97/0/98/0/99/
Response.write rslt & "<br>"

m = split(rslt,"/")
mleng = UBound(m)
Response.write mleng & "<br>"
'출력결과비교:
'php: 13
'asp: 17

for i=0 to mleng-1
  th = th & chrB(m(i))
next
Response.write th
'출력결과: 123가나다abc
%>

위에서 보듯이, php 코드를 asp 코드로 바꾸는데 있어서는 항상 바이트 단위를 염두에 두고 있어야 하며,
이를 잊어버리고 있다가 헤메는 일이 없도록 해야 한다.

php 출력화면

asp 로 코드를 바꾼후의 출력화면

[asp] ascB(), chrB(), midB(), lenB() 와 php 의 ord(),chr(),substr(),strlen() 비교

'-- PHP' 카테고리의 다른 글

Apache에 PHP설정  (0) 2012.09.10
require, require_once, include, include_once  (0) 2012.07.18
PHP (hex2bin, bin2hex) convert ASP  (0) 2009.07.30
php 함수 리스트  (0) 2009.07.29
PHP에서 Asp처럼 CreateObject 쓰기  (0) 2007.11.02
posted by 어린왕자악꿍