Admin | Write | GuestBook
[공지] 해당 블로그에 용건이 있으신 분께서는 http://blog.fore.kr/ 의 방명록(Guestbook)으로 부탁드립니다.
[C/C++] 한글 판별 코드.
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2014. 12. 16. 09:44 ) | 신고

 

 

아오... 만들긴 귀찮고, 인터넷에 이정돈 떠돌아 다니겠지 했는데 없음 -_- . . .

 

찾아도 죄다 유니코드로 판별.(이것조차도 불완전함.)

 

ANSI 코드는 죄다 0x80 으로 비교분석하고 끝남.

( 이러면 문제가 되는게, 한글외 전각문자 예를 들면 ★, あ와 같은 것들도 한글로 처리됨. )

 

IsDBCSLeadByte 함수 또한 싱글바이트로 들어가서 순수 한글을 판단하는건 불가능함.

( 아마, 코드페이지에 해당하는 전각 문자열 범위로 판단하는듯 함. )

 

결론은 그냥 직접 작성함.

 

이거 어렵지 않고 단순 노가다인데 왜 안보이지 -_- . . .

( 검색어가 좋지 않았나 . . . )

 

//  IsHangulString

// Present by FORE

// http://foreblog.tistory.com/

 

#include <windows.h>


BOOL WINAPI IsHangulStringA(LPSTR lpString){
 BYTE   ch1,ch2;
 while(*lpString){
  ch1 = (BYTE)*lpString;
  if ( ch1 & 0x80 ){
   ch2 = (BYTE)*(lpString+1);
   if ( (ch1>0x80 && ch1<=0xA0) || (ch1>=0xB0 && ch1<=0xC5) ){
    if ( (ch2>0x40 && ch2<0x5B) || (ch2>0x60 && ch2<0x7B) || (ch2>0x80 && ch2<0xFF) )
     return TRUE;
   }
   else if ( ch1>0xA0 && ch1<0xB0 ){
    if ( (ch2>0x40 && ch2<0x5B) || (ch2>0x60 && ch2<0x7B) || (ch2>0x80 && ch2<0xA1) )
     return TRUE;
    if ( ch1 == 0xA4 ){ // 여기가 자모 코드. 자모 판별 필요 없을시 제거 가능.
     if ( ch2>0xA0 && ch2<0xFF )
      return TRUE;
    }
   }
   else if ( ch1 == 0xC6 ){
    if ( (ch2>0x40 && ch2<0x53 ) || (ch2>0xA0 && ch2<0xFF) )
     return TRUE;
   }
   else if ( ch1 > 0xC6 && ch1 < 0xC9 ){
    if ( ch2>0xA0 && ch2<0xFF )
     return TRUE;
   }
   lpString++;
  }
  lpString++;
 }
 return FALSE;
}

 

BOOL WINAPI IsHangulStringW(LPWSTR lpString){
 WCHAR   ch1;
 while(*lpString){
  ch1 = *lpString;
  if ( (ch1 >= 0xAC00 && ch1 <=0xD7A3)
   || (ch1 >= 0xA960 && ch1 <=0xA97C) // 이 밑부터 죄다 자모 코드
   || (ch1 >= 0xD7B0 && ch1 <=0xD7C6)
   || (ch1 >= 0xD7CB && ch1 <=0xD7FB)
   || (ch1 >= 0x3131 && ch1 <=0x318E) )
   return TRUE;
  lpString++;
 }
 return FALSE;
}

 

 

 

IsHangulStringA 의 수많은 if를 한줄로 줄이면

 

BOOL WINAPI IsHangulStringA(LPSTR lpString){
 BYTE   ch1,ch2;
 while(*lpString){
  ch1 = (BYTE)*lpString;
  if ( ch1 & 0x80 ){
   ch2 = (BYTE)*(lpString+1);
   if ( (((ch1>0x80 && ch1<=0xA0) || (ch1>=0xB0 && ch1<=0xC5)) && ((ch2>0x40 && ch2<0x5B) || (ch2>0x60 && ch2<0x7B) || (ch2>0x80 && ch2<0xFF)))
    || ((ch1>0xA0 && ch1<0xB0) && (ch2>0x40 && ch2<0x5B) || (ch2>0x60 && ch2<0x7B) || (ch2>0x80 && ch2<0xA1))
    || ((ch1 == 0xA4) && (ch2>0xA0 && ch2<0xFF))
    || ((ch1 == 0xC6) && ((ch2>0x40 && ch2<0x53 ) || (ch2>0xA0 && ch2<0xFF)))
    || ((ch1 > 0xC6 && ch1 < 0xC9) && (ch2>0xA0 && ch2<0xFF)) )
     return TRUE;
   lpString++;
  }
  lpString++;
 }
 return FALSE;
}

 

이리되는데, 결국 작동속도는 똑같을 것으로 보인다.

 

 

IsHangulString.c

 

[Python] 파이썬 2.7 유니코드 관계
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2014. 12. 13. 01:44 ) | 신고

 

 

윈도우 프로그래밍에서 MultiByteToWideChar 혹은 WideCharToMultiByte 를 사용해본 분이라면

 

아마, 이해하기 쉬우실 듯 합니다.

 

인터넷에서 파이썬 유니코드 글들을 찾아보면 제일 큰 오해를 하고 있는것들이

 

' UTF-8 = 유니코드 '

 

로 이해하는 글들이 너무나 많다.

 

이게 틀린건 아닌데, 맞는거도 아니다. 정확힌 틀리다고 보는게 맞다.

 

문자 인코딩에는 크게 ANSI - 유니코드(UTF-16) - UTF-8 등이 존재한다.

( 즉, 유니코드와 UTF-8 은 별개의 문자열이다. )

정정 : 문자 인코딩에는 크게 ANSI, UTF-16, UTF-8 등이 존재한다.

이 중 UTF-16과 UTF-8 은 유니코드라는 범위에 속하며, 통상 UTF-16 을 유니코드라고 부른다.

 

자세한건 Wiki 참조.

유니코드 : http://ko.wikipedia.org/wiki/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C

UTF-8 : http://ko.wikipedia.org/wiki/Utf-8

 

추측인데, 파이썬을 아무런 조작을 해두지 않은 상태라면 기본 ANSI로 실행되는 듯하다.

( 이 ANSI 라는게 반드시 한국어로 되라는 법은 없다. OS 언어 설정에 따라 이 ANSI 값은 바뀌게 된다. )

 

한가시 실험을 해보면 아래와 같다.

 

 

ascii = ANSI, utf-8, euc-kr 페이지는 따로 존재하는걸 볼 수 있다.

 

따라서, 기본 '유니코드' 로 코딩하는게 제일 안전하다는게 필자의 결론이다.

 

아래는 몇가지 예이다.

 

 

< 유니코드로 문자열로 저장시키기 >

 

>>> s = u'포레'

>>> print s

u'\uf7c6\ub9b7'

 

 

< ANSI를 유니코드로 변경 >

 

>>> s = '포레'

>>> s = s.decode('utf-16-le')

>>> print s

u'\uf7c6\ub9b7'

 ※ le는 little-endian, be는 big-endian 을 의미한다. 자세한 내용은 Wiki 참고.

http://ko.wikipedia.org/wiki/%EC%97%94%EB%94%94%EC%96%B8

 

 

< 유니코드 문자열을 유니코드 문자열로 파일 저장 >

 

>>> f = open(u'C:\\text_test.txt',u'w')

>>> s = u'포레'

>>> # 유니코드 텍스트 파일 시그니쳐

>>> f.write('\xff\xfe')

>>> # 버퍼를 저장.

>>> f.write(s.encode('utf-16-le'))

>>> f.close()

 

 

일반 함수에서 자연스럽게 유니코드 문자열을 넣으면 자동적으로 인식하는건

 

아마 PyObject 에 있는 구조체를 인식해서 그때그때 상황에 맞춰 함수 호출이 달라지는 듯 하다.

 

 

- 부록 -

 

# coding: (코드 페이지)
이녀석은 추측컨데, 해당 파이썬 스크립트를 (코드 페이지)로 인식시키는 듯하다.

 

# coding:utf-8 

# 이 밑으로 전부 utf-8 문자열로 컴파일링을 실시한다.

print '포레' .decode('utf-8').encode('euc-kr')

 

이녀석이 좀 많이 골치 아픈데, 위에 '포레' 라는 단어는 내부에서 바이트 그대로 읽어들여

 

포레 = 'ED 8F AC EB A0 88' 로 읽어들이게 된다. (utf-8)

 

이걸 그대로 사용하면 함수 등에 문제가 있으며

 

이걸 반드시 위와 같이 'ANSI'나 '유니코드' 로 바꿔줄 필요가 있다.

 

한가지 재미있는 예로 utf-16-le 코드 페이지로 설정하면 아래와 같이 된다.

 

py_codepage_utf16-le.py

 

메모장 등으로 열면 잘 안열리는데 아래와 같은 소스다.

 

#coding:utf-16-le (여기까지 ANSI)
( 이 밑부터 유니코드 페이지 속성으로 코딩 )

import sys
import msvcrt

 

 

print sys.getdefaultencoding()
print 'test'
print 'test'.decode(u'utf-16-le')
msvcrt.getch()

 

 

조잡하긴 한데, 열린다.

 

결과를 보면 test 부분은 하나씩 스페이스가 들어간 마냥 출력되는데

 

이는 't\x00e\x00s\x00t\x00' (ascii bytes) 으로 들어갔기 때문.

 

따라서, 위 코드를 쓸 때에는 조금 신경써서 코딩하는게 중요할 듯 하다.

 

 

setdefaultencoding (코드 페이지)

현재 실행되고 있는 파이썬 프로그램의 기본 언어 상태를 (코드 페이지)로 변경한다.

설명은 위와 비슷한듯 하지만, 전혀 다르다.

스크립트 자체 해석은 위에서 설명했던 코드 페이지에서 해석하는데

기본 시스템 언어로 설정된 함수에 한해서 setdefaultencoding 함수로 설정된 코드페이지에 맞춰

처리된다.

 

setdefaultencoding.py

 

위 파일 참고.

 

타언어 → 유니코드 → 텍스트 파일(euc-kr)로 저장.

( 예제는 일본어로 함. )

 

>>> f = open(u'ja.txt',u'r')

>>> b = f.read() 

>>> f.close()

>>> f = open(u'ko.txt','w')

>>> b = b.decode('shift-jis')

>>> # b 는 유니코드(utf-16-le) 상태

>>> b = b.encode('euc-kr')

>>> f.write(b)

>>> f.close()

 

언어별 인코딩 방식은

https://docs.python.org/2/library/codecs.html#standard-encodings

에서 확인할 수 있다.

 

 [ 테스트 파일 첨부 ]

ja.txt

 

결과가 あいうえお 로 나오면 정상적으로 처리됨.

 

생각컨데 여기까지 달리면 파이썬 유니코드 프로그래밍 하는건 크게 어렵지 않다고 본다.

 

 

'Programming > Programming Talk' 카테고리의 다른 글

[Python] pf2  (8) 2014.12.16
[C/C++] 한글 판별 코드.  (2) 2014.12.16
Thumbs.db 파일에 관한 고찰  (3) 2014.12.06
[Python] 동적 라이브러리(DLL) 사용 처리.  (0) 2014.12.03
[Python] 윈도우 다이어로그 생성  (0) 2014.12.02
Thumbs.db 파일에 관한 고찰
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2014. 12. 6. 18:01 ) | 신고

 

 

( ’ ω’)

 

[시험해볼 DB 파일]

Thumbs.db

 

토나코이 어카이브를 전부 풀고, 덤으로 Thumbs.db 파일이 보여 이 파일에 대해 잠깐 분석해보았다.

 

일단, 자세한 설명에 앞서, Thumbs.db 파일은 기본적으로 OLE 구조로 아래의 프로그램으로 풀 수 있다.

 

http://foreblog.tistory.com/730

 

OLE 구조에 대해선 위 링크의 pdf 문서를 보면 자세히 알 수 있다.

 

풀고보면 안보이는 경우가 대다수인데, 뭔지 모르겠는데 또 패킹되어 있다.

 

 

이런식으로 패킹되어 있다.

( 가운데 3은 뭔가 타입인듯 한데, 분석할 파일 수도 적어서 분석 불가...

하지만, 가운데 숫자 없어도 푸는덴 지장 없음. )

 

StructSize 크기는 최소 0x0C 크기를 갖고, 그 뒤로 넘어가는 코드는 정확히 뭔지 모르겠다.

( 개인적인 추측으론 File Size 뒤 4bytes 의 0은 reserved. 뒤 8bytes 는 Time Stamp 로 추정됨. )

 

Structure Size 다음 오프셋으로 넘어가면 FF D8 부분이 보이고

 

조금만 옆을 더 보면 JFIF 라는 부분이 보이는데 조금만 검색해보면 JPEG 포멧인걸 알 수 있다.

 

JPEG 포멧의 끝 부분은 FF D9 라는 오프셋이 붙는데, 한번 확인해보자.

 

끝 오프셋 계산 : File Size (0x095F) + Struct Size (0x18) = 0x0977

 

 

끝 부분이 FF D9 이므로 JPEG 인건 확실해졌다.

 

이를 통해, 언패킹하면 . . .

 

 

 

매우 잘 보인다.

 

덤으로 이에 관련한 파이썬 소스

 

ThumbsInFile.py

 

[Python] 동적 라이브러리(DLL) 사용 처리.
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2014. 12. 3. 03:18 ) | 신고

 

 """
Load Dynamic-Linked Library(DLL) in Python 2.7
Present by FORE
http://foreblog.tistory.com/
"""

from ctypes import *

 

# define win32-api function
LoadLibraryW = windll.kernel32.LoadLibraryW
GetProcAddress = windll.kernel32.GetProcAddress

 

# Start script
user32 = LoadLibraryW(u'USER32.DLL')
MessageBoxA = GetProcAddress(user32,'MessageBoxA')
if MessageBoxA == 0:
 print 'out!'
 exit()

 

# if __cdeal type -> use CFUNCTYPE
pMessageBoxA = WINFUNCTYPE(c_uint,c_void_p,c_char_p,c_char_p,c_uint)
MessageBoxA = pMessageBoxA(MessageBoxA)
MessageBoxA(0,'XD','Caption',0)

 

 

 

 

[Python] 윈도우 다이어로그 생성
Category : Programming/Programming Talk | URL : | Written by 포레 ( 2014. 12. 2. 18:38 ) | 신고

 

[やったぜ!]

 

파이썬으로 윈도우에서 윈도우(혹은 다이어로그)를 생성할 수 있을까 . . .

 

사용자가 만든 템플릿을 쓰면 매우 간단하게 풀리겠지만, 오기로 ctypes 에서 직접 함수를 불러와

 

직접 구현해보았다. (디짐 -_-...)

 

"""
Show Dialog in Python 2.7
Present by FORE
http://foreblog.tistory.com/
"""

 

from ctypes import *
from ctypes.wintypes import *
from msvcrt import *

 

# define win32 api function
DialogBoxIndirectParamW = windll.user32.DialogBoxIndirectParamW
PostQuitMessage = windll.user32.PostQuitMessage
DestroyWindow = windll.user32.DestroyWindow
EndDialog = windll.user32.EndDialog
CreateWindowExW = windll.user32.CreateWindowExW
SetWindowTextW = windll.user32.SetWindowTextW
GetClientRect = windll.user32.GetClientRect

GetModuleHandleW = windll.kernel32.GetModuleHandleW

 

# define callback function type
DLGPROC = WINFUNCTYPE(c_uint, HWND, c_uint, WPARAM, LPARAM)

 

# define window style
WS_VISIBLE = 0x10000000
WS_POPUP = 0x80000000
WS_CAPTION = 0x00C00000
WS_SYSMENU = 0x00080000
WS_CHILD = 0x40000000

 

# define window message
WM_INITDIALOG = 0x0110
WM_CLOSE = 0x0010
WM_DESTROY = 0x0002

 

# define structure
class DLGTEMPLATE(Structure):
 _fields_ = [
 ('style',c_uint),
 ('dwExtendedStyle',c_uint),
 ('cdit',c_ushort),
 ('x',c_short),
 ('y',c_short),
 ('cx',c_short),
 ('cy',c_short),
 ('id',c_uint)
 ]

 

# define callback function
def cb_wndproc(hwnd,msg,wparam,lparam):
 if msg == WM_INITDIALOG:
  SetWindowTextW(hwnd,u'Python Dialog')
  r = RECT()
  GetClientRect(hwnd,r)
  CreateWindowExW(0,u'Static',u'Show',WS_CHILD|WS_VISIBLE,(r.right-50)/2,(r.bottom-30)/2,50,30,hwnd,0,0,0)
  del r
 elif msg == WM_CLOSE:
  DestroyWindow(hwnd)
 elif msg == WM_DESTROY:
  EndDialog(hwnd,0)
 return 0

 

# Start
dtp = DLGTEMPLATE()
memset(byref(dtp),0,sizeof(DLGTEMPLATE))
dtp.style = WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU
dtp.cx = 100
dtp.cy = 100

hInstance = GetModuleHandleW(0);
DialogBoxIndirectParamW(hInstance,byref(dtp),0,DLGPROC(cb_wndproc),0)

 

 

Dialog.py

 

 

뭐 이건 . . . 하나하나 다 로딩해줘야함 -_- ;

 

※ 스크립트 복사해서 파이썬 스크립터 내에서 직접 돌리고자 할 경우

hInstance 부분을 직접 불러줘야 한다. ( 아직도 왜그런지 이유를 못찾고 있음... )

 

Category
분류 전체보기 (605)
Notice (6)
Programming (79)
Release Program (19)
Release Patch (14)
Programming Talk (46)
DISKER (1)
FSCH (7)
Caption (0)
Rest Time ! (443)
Hobby (64)
Tour (5)
Blind Post (0)
Recent Post
Recent Comment
Link
Calender
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Total :
Today :
Yesterday :