delphi5] utf-8 to unicode to ansi(euc-kr)... method

간만에 delphi 를 돌려서
url 을 근거(?)로 html 내용을 받아볼까...라는 생각을 하고 시도(?)를 했는데,

1) drag&Drop... 이 부분이 막혀서, 결국 dragNdrop Component 를 다운받아 설치하고,... (이 방법으로 해결...)

2) 요즘 html 파일에 utf-8 이 거의 기본으로 설정되어 있었다... 해석해야하는데...

=.=... 이런 여러가지(?)문제를 받아서, 처리하는 과정이 생겨버렸다.
뭐... 어느정도까지 해결을 하다가, 일단 기록해본다.

...

*참고*
: - Pascal Newsletter #3 - 
http://dolba.net/tt/k2club/entry/Tip-델파이에서의-UTF-8-STRINGS의-포팅하기?category=34 
: - 마음의 안정을 찾기 위하여 -

이진법으로 표시하면 편리하게 구조를 볼 수 있었다

이전까지는 utf-8 이 그냥 "확장을 위한 스트링 구조체겠구나..."라는 막연한 생각만 했었는데... 생각보다 길었다.
( 분석 조금 해보니, 예전에 string 압축할 때의 생각과 얼추 비슷했다. 뭐... 그건 그렇다는거고... )

... 그래서, 만든 샘플이...

...


procedure TForm1.Button3Click(Sender: TObject);
var
  i, tlength, ov1, ov3, ov4, lov1, wl : longword;
  ttext, ov2, ov5 : string;
  cc, cplus, j, cdp : byte;

  wbuff : array[0..1023] of widechar;
begin
  ttext:=memo2.lines.text;
  tlength:=length(ttext);
  i:=4; // skip pre $EFBBBF (utf-8 header)


  ov5:=''; wl:=0;


  while i<=tlength do begin
    cc:=ord(ttext[i]);
    if (cc and $80)=$80 then begin
      if (cc and $c0)=$80 then cplus:=0
      else if (cc and $e0)=$c0 then cplus:=1
      else if (cc and $f0)=$e0 then cplus:=2
      else if (cc and $f8)=$f0 then cplus:=3
      else if (cc and $fc)=$f8 then cplus:=4
      else if (cc and $fe)=$fc then cplus:=5
      else if (cc and $ff)=$fe then cplus:=6
      else begin
        showmessage('what is this?');
        break;
        end;


      ov1:=((cc shl (cplus+2)) and $ff) shr (cplus+2);
      ov2:=binaryOut(
        ( (cc shl (cplus+2)) and $ff ) shr (cplus+2), 6, 6);
      for j:=1 to cplus do begin
        cc:=ord(ttext[i+j]);
        if (cc and $c0)=$80 then begin
          ov1:=(ov1 shl 6) or (cc and $3f);
          ov2:=ov2+binaryOut(cc and $3f, 6, 6)+' ';
          end
        else begin
          showmessage('what is outs?'+inttohex(cc, 2)+' '+inttostr(cplus));
          break;
          end;
        end;


      inc(i, cplus);
      end
    else
      ov1:=cc;


//      showmessage(binaryOut(ov1, 64, 6)+'/'+ov2);
    wbuff[wl]:=widechar(ov1);
    inc(wl);


    if wl>=1023 then begin
      wbuff[wl]:=widechar(0);
      ov5:=ov5+widechartostring(wbuff);
      wl:=0;
      end;


    inc(i);
    end;

  wbuff[wl]:=widechar(0);
  ov5:=ov5+widechartostring(wbuff);

  memo1.Lines.text:=ov5;
end;


...

=.=;... 함수로 바로 쓸 수 있게 만든게 아니고,
급한대로(?) 이것저것 짜깁기해버렸다. (확장을 위해 만든 것이 아니니, 급할땐 좀 자제를...)

...

1) utf-8 -> unicode

음... memo1 에 있는 내용을 불러와서 (아직 변환 전...)
스트링들을 utf 로 얼마나 읽어야 한글자로 판단해주는지 측정(?)한 다음, (이진법으로 1이 0 이전에 얼마나 채워졌는지...)

코드로 넘겨줄 글자들을 수집해서 wbuff 로 widechar 형식을 빌려 넘겨준다.

거기까지가 utf-8 to unicode...

...

2) unicode -> ansi...

이 표현이 맞는지 모르겠다.
wbuff 를 이용해서 수집한 내용들을 TMemo 에서 사용할 수 있도록 ansi 형태의 string 으로 바꿔주는 것.

하나면 충분했다.

ov5 := widechartostring( wbuff );

언어형식(한국어면 euc-kr... CP949 인가...?)으로 넘겨주기 위해 코드페이지가 필요하지 않을까...싶었는데,
-.-? 따로 안불러도 잘 되는 듯...

...

=.=... 사실, 저걸 몰라서, 다시 ansi 로 encoding 해야하나...를 두고,
직접(?) encoding 하기도 했는데... 작동을 안하길래 검색을 하다가... 문득 생각난게 위키쪽 페이지들...

= =;... 각국 언어가 틀린데, ansi 로 바로 전환될 리가 없잖아...

*참고* - 유니코드 A000~AFFF - : http://wikipedia.org/

...

3)
뭐... 살짝 부족한 면이 있다.
국가별 언어설정에 맞춰서 widechartostring 이 바껴야하는 것 아닐가...하는 부분...

= =;... 나중에 찾으면 다시 적을 수 있으려나...? (OTL... 찾아보니 뭔가 어려운게 잔뜩 적혀있다...)
http://www.delphipages.com/forum/showthread.php?t=165093 

...

4)
버그(?)도 있다.

마지막글자 하나에서 오류가 나는 것...
마지막 글자가 ASCII 코드면 문제가 안되는데, unicode 형식이라 그런지 오류가 나버린다...
= =;... 우짤꼬...

('10.06.04 17:03 추가)
(뭐... utf-8 코드를 강제(?)로 읽은 탓도 있겠지만...)

...

그리하여(?)... 마무리...

...


function utf8toansi(v : string; startpoint : integer) : string;
var
  i, vl, wp : cardinal;
  cc : byte;
  wbuff : array[0..1024] of widechar;
  wv : cardinal;
  ov : string;
begin
  i:=startpoint; vl:=length(v); wp:=0; ov:='';
  while i<=vl do begin
    cc:=ord(v[i]);
    if cc and $80=0 then begin wv:=cc; inc(i);
      end
    else begin
           if cc and $e0=$c0 then begin
        wv:=((cc and $3f)shl 6) or (ord(v[i+1])and $3f); inc(i, 2);
        end
      else if cc and $f0=$e0 then begin
        wv:=((cc and $1f)shl 12)
          or ((ord(v[i+1])and $3f)shl 6) or (ord(v[i+2])and $3f); inc(i, 3);
        end
      else if cc and $f1=$f0 then begin
        wv:=((cc and $1f)shl 18)
          or ((ord(v[i+1])and $3f)shl 12) or ((ord(v[i+2])and $3f)shl 6)
          or (ord(v[i+3])and $3f); inc(i, 4);
        end
      else if cc and $f2=$f1 then begin
        wv:=((cc and $07)shl 24)
          or ((ord(v[i+1])and $3f)shl 18) or ((ord(v[i+2])and $3f)shl 12)
          or ((ord(v[i+3])and $3f)shl 6) or (ord(v[i+3])and $3f); inc(i, 5);
        end
      else inc(i);
      end;
    wbuff[wp]:=widechar(wv); inc(wp);
    if wp>=1024 then begin
      wbuff[wp]:=widechar(0); ov:=ov+widechartoString(wbuff); wp:=0;
      end;
    end;
  wbuff[wp]:=widechar(0); ov:=ov+widechartoString(wbuff);
 
  utf8toansi:=ov;
end;


...

NowMark killofki@.




덧글

  • 자유사랑 2010/06/22 12:45 # 삭제 답글

    메신저 프로토콜에서 UTF-8을 사용해서 처리방법을 찾다가 들렀습니다.
    좋은 정보 감사드립니다
  • killofki 2010/06/23 09:36 #

    ^^;... 네...
댓글 입력 영역

분석기


한국파워블로거협동조합 배너

http://cafe.naver.com/powerbloggeraliance

구글 Adsense

구글검색

애드센스 긴거

meta Loader