2008. 12. 16. 14:09

루비 온 레일스로 파일업로딩

원본은  http://www.tutorialspoint.com/ruby-on-rails/rails-file-uploading.htm 이고,
대충 번역했다.




Rails를 이용한 파일업로딩


레일즈 명령어를 이용해 어플리케이션 본체 생성

C:\ruby> rails upload

업로드될 파일의 위치 결정. 이 자료들은 공용 구역에 저장됨
디렉터리를 만들고 퍼미션 체크


C:\ruby> cd upload
C:\ruby> mkdir upload\public\data
 

다음은 컨트로러와 모델 생성

모델 생성:
DB기반 어플리케이션이 아니기 때문에 아무 이름가능. DataFile 모델로 만듬.
(주:테이블에 대한 1또는 n에 대한 단/복수형 모델명을 지정을 해야되기 때문에..?)


C:\ruby> ruby script/generate model DataFile
      exists  app/models/
      exists  test/unit/
      exists  test/fixtures/
      create  app/models/data_file.rb
      create  test/unit/data_file_test.rb
      create  test/fixtures/data_files.yml
      create  db/migrate
      create  db/migrate/001_create_data_files.rb


data_file.rb 모델 파일에서 불러질 메소드(액션메소드?)를 생성한다.
이 메소드는 어플리케이션 컨트롤러에서 사용될 것이다.


class DataFile < ActiveRecord::Base
  def self.save(upload)
    name =  upload['datafile'].original_filename
    directory = "public/data"
    # create the file path
    path = File.join(directory, name)
    # write the file
    File.open(path, "wb") { |f| f.write(upload['datafile'].read) }
  end
end


위 함수는 CGI 객체 [업로드]를 받고 업로드된 파일명을 [original_filename] 함수를
이용해서 추출해(extract)주고, "public/data" 디렉터리에 저장될 것이다.
또한 [content_type] 함수를 이용해서 미디어 형식(mime?)을 불러올 수 있다.
 

여기서 [File]은 루비 객체이고 디렉터리명과 파일명을 합쳐서
전체파일경로(full file path) 를 리턴한다.


그 다음, File 객체에서 제공해주는 함수로 쓰기모드(write mode)로 연다.
또한 읽어진 파일을 출력파일로 쓸 수 있다.


컨트롤러 생성:
업로드용 컨트롤러 생성


C:\ruby> ruby script/generate controller Upload
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/upload
      exists  test/functional/
      create  app/controllers/upload_controller.rb
      create  test/functional/upload_controller_test.rb
      create  app/helpers/upload_helper.rb
 

Now we will create two controller functions first function index will call a view file to take user input and second function uploadFile takes file information from the user and passes it to the 'DataFile' model. We set the upload directory to the 'uploads' directory we created earlier "directory = 'data'".

2개의 컨트롤러 함수를 만들건데, 하나는 뷰 파일에서 입력을 받을 [index] 이고,
다른 함수는 [uploadFile]로, 사용자가 DataFile 모델을 통해 올려진 파일의 정보를
얻는 것이다. 앞에서, uploads 디렉터리에 저장하기위해 "directory = data" 로 했다.
 

class UploadController < ApplicationController
  def index
     render :file => 'app\views\upload\uploadfile.rhtml'
  end
  def uploadFile
    post = DataFile.save(params[:upload])
    render :text => "File has been uploaded successfully"
  end
end
 

불러올 함수를 모델파일에 정의한다. [render] 함수는 view 파일로 메시지를
되돌려서 보여준다.


뷰 생성:
마지막으로 컨트롤러에서 언급한 [uploadfile.rhtml] 뷰 파일을 만든다.
대충 다음처럼..


<h1>File Upload</h1>
<%= start_form_tag ({:action => 'uploadFile'},
                        :multipart => true) %>
<p><label for="upload_file">Select File</label> :
<%= file_field 'upload', 'datafile' %></p>
<%= submit_tag "Upload" %>
<%= end_form_tag %>
 

여기까지가 설명한 모든 것들이다.
새로운 태그는 [file_field] 뿐이고, 이는 사용자의 컴퓨터에서 파일을 찾을 수 있는
버튼을 만들어준다.


multipart 파라미터를 참(true)로 설정하면, 파일을 binary file 형식으로 바로
인식한다.

여기서 중요한 것은 :action 에 메소드이름을 [uploadFile] 으로 업로드 버튼을 누르면
호출하기 위해서 지정한 것이다.

이는 다음화면처럼 보여준다.

[http://www.tutorialspoint.com/images/upload-file.gif]


업로드하면 app/public/data 디렉터리에 실제 파일명으로 저장되고 메시지가 보여진다.

NOTE: 디렉터리에 같은 파일명이 이미 존재하면 덮어쓸 것이다.

------------------------------------
대충 번역은 여기까지..
------------------------------------


Files uploaded from Internet Explorer:
Internet Explorer includes the entire path of a file in the filename sent, so the original_filename routine will return something like:


Files uploaded from Internet Explorer:
Internet Explorer includes the entire path of a file in the filename sent, so the original_filename routine will return something like:

C:\Documents and Files\user_name\Pictures\My File.jpg
 

instead of just:

My File.jpg
 

This is easily handled by File.basename, which strips out everything before the filename.

def sanitize_filename(file_name)
  # get only the filename, not the whole path (from IE)
  just_filename = File.basename(file_name)
  # replace all none alphanumeric, underscore or perioids
  # with underscore
  just_filename.sub(/[^\w\.\-]/,'_')
end
 

Deleting an existing File:
If you want to delete any existing file then its simple and need to write following code:

  def cleanup
    File.delete("#{RAILS_ROOT}/dirname/#{@filename}")
            if File.exist?("#{RAILS_ROOT}/dirname/#{@filename}")
  end
 

For a complete detail on File object, you need to go through Ruby Reference Manual.

[출처] http://guyv.tistory.com/201

2008. 11. 27. 10:58

유니코드에서 초,중,종성 분리

주의:

  PB v4.0에서 UTF-8 소스 인코딩을 선택하고, 컴파일 옵션은 유니코드 실행 파일

  설정하고 아래 코드를 실행한다.

 

 

C++ 코드와 설명 출처: 데브피아

 

;- 유니코드 한글의 자모 분리법.
;
;
; 유니코드 완성형 한글 코드는 배치가 매우 잘되어 있어서 초성 중성 종성의 분리가 가능하다.
;
; wchar_t CompleteCode = L'가';
; 이렇게 완성형 코드가 있을 때
;
; wchar_t UniValue = CompleteCode - 0xAC00;
;
; 0xAC00은 한글 코드의 시작 값이다. 따라서 저 값을 빼면
; 우선적으로 우리가 원하는 한글 값만을 가지게 된다.
;
; 이제 저장한 UniValue로부터 종성을 분리한다.
; wchar_t Jong = UniValue % 28;
;
; 유니코드에서 사용가능한 초성은 19개, 중성은 21개, 종성은 28개이고
; 유니코드가 같는 값의 공식은
;
; 유니코드 완성형 값 = ( ( ( 초성 * 21 ) + 중성 ) * 28 ) + 종성 + 0xAC00;
;
; 이렇게 된다. 따라서 UniValue에서 28로 나눈 나머지는 종성이 된다.
;
; 이번에는 중성을 찾는다.
; wchar_t Jung = ( ( UniValue - Jong ) / 28 ) % 21;
; wchar_t Cho = ( ( UniValue - Jong ) / 28 ) / 21;
;
; 이렇게 하여 유니코드 완성형 값에서 초성, 중성, 종성의 값을 분리해낼 수 있다.
; 주의할 점은 저렇게 나오는 값은 인덱스 값이라는 점이다.
; 정확한 자모 값을 받기 위해서는 유니코드 한글 자모 코드표를 통해서
; 초성에는 초성 시작 값을 더해주고, 중성에는 중성 시작값을,
; 종성에는 종성의 시작값을 더해주어야 정확한 자모 값을 얻을 수 있다.
;
; 자, 이제 코드를 살펴보자...
;
; // unicode3.cpp
; #include <windows.h>
; #include <iostream>
; #include <locale>
;
; using namespace STD;
;
; INT main()
; {
;         wcout.imbue( locale("korean") );
;
;         wchar_t CompleteCode = L'개';
;         wchar_t UniValue = CompleteCode - 0xAC00;
;
;         wchar_t Jong = UniValue % 28;
;         wchar_t Jung = ( ( UniValue - Jong ) / 28 ) % 21;
;         wchar_t Cho = ( ( UniValue - Jong ) / 28 ) / 21;
;
;         cout << "초성 : " << Cho << "\t" << "중성 : " << Jung << "\t" << "종성 : " << Jong << endl;
; }
;
; 위와 같은 코드를 작성하여 살펴보면 '개'의 초성은 'ㄱ'이고, 중성은 'ㅐ', 종성은 없다.
; 따라서 'ㄱ'은 자모 코드 중 초성의 첫번째이므로 0의 값을 가지며,
; 'ㅐ'는 중성의 두번째이므로 1의 값을 가지고 종성은 없으므로 0의 값을 가지게 된다.
; 문제점은 종성의 0이다. 한글 코드는 초성이 없는 경우가 없고, 중성이 없는 경우는 없으나
; 종성이 없는 경우는 있다. 따라서 종성의 인덱스는 1부터 시작해야 한다.
; 저 위의 코드 중 L'개'를 L'객'으로 바꿔 살펴보면 종성 값이 1로 나오는 것을 확인할 수 있다.
;
; 유니코드의 자모값의 코드표에 대하여 알고 싶을 경우
;
http://www.unicode.org/charts/PDF/U1100.pdf
;
; 그리고 한글 완성형 코드표에 대하여 알고 싶을 경우
;
http://www.unicode.org/charts/PDF/UAC00.pdf
; 위의 링크에 가면 된다.


UniValue = Asc("객") - $AC00
Debug UniValue

 

jong = UniValue % 28
jung = ( ( UniValue - jong ) / 28 ) % 21
cho = ( ( UniValue - jong ) / 28 ) / 21

 

;각각의 인덱스 출력.
Debug cho
Debug jung
Debug jong

 

;실제 자모의 출력.
Debug Chr(cho+$1100)
Debug Chr(jung+$1161)
If jong   ;종성이 있으면 이하 처리.
  Debug Chr(jong+$11a7)
EndIf

 

 

실행 결과

 29
 0
 1
 1
 ㄱ
 ㅐ
 ㄱ

 


2008. 11. 19. 14:07

MFC에서 현재 실행 중인 응용프로그램 목록 얻어오기


EnumWindows라는 함수는 윈도우 운영체제 상의 모든 윈도우 목록을 조사해서
콜백함수로 넘겨줍니다. 콜백함수로 넘겨지는 데이터는 윈도우의 핸들이 되겠구
요. 콜백함수에서는 넘겨받은 핸들을 이용하여 윈도우 핸들로 가능한 모든 작업
을 할 수 있습니다. 말하자면, 윈도우의 캡션이라든가 Rect 좌표 같은 정보를 알
아내거나 해당 윈도우로 메시지를 보낸다든지 하는 그런 것들 말이죠.

MSDN에서 따온 함수원형은 아래와 같습니다.

BOOL EnumWindows(
  WNDENUMPROC
lpEnumFunc// pointer to callback function
  LPARAM lParam            // application-defined value
);

lpEnumFunc 이라는 놈은 보시다시피 콜백함수의 포인터라는군요.
다음으로 lParam 라는 놈이 나오는데요 다들 알고 계시겠죠??

자 그럼 실제로 EnumWindows라는 함수를 한 번 써보겠습니다.

먼저 함수의 첫번째 파라미터로 넘겨줄 콜백함수를 만들어야겠지요?
저는 EnumWindowCallBack이라는 이름으로 만들었습니다.

BOOL CALLBACK EnumWindowCallBack(HWND hwnd, LPARAM lParam);

함수의 내부는 다음과 같이 만들었습니다.

BOOL CALLBACK EnumWindowCallBack(HWND hwnd, LPARAM lParam)
{
 char Cap[255];
 RECT rt;
 CString HwndInfo;
 int length;

 GetWindowText(hwnd, Cap, 255);
 length = GetWindowTextLength(hwnd);
 GetWindowRect(hwnd, &rt);
 
 if (IsWindowVisible(hwnd) && length > 0)
 {
  HwndInfo.Format("%s", Cap, rt.left, rt.top, rt.right, rt.bottom);
  pDlg->m_comboControl.AddString(HwndInfo);
  pDlg->OpenWindow[pDlg->count] = hwnd;
 }
 return TRUE;
}

EnumWindows 함수로부터 hwnd라는 윈도우의 핸들을 가지고 놀아봅시다.
GetWindowText 함수를 이용해서 해당 윈도우의 캡션을 Cap이라는 배열에
저장하고 캡션의 길이를 length에 저장합니다. Rect를 얻어오는건 제가 필요
해서 한거구요...없어도 실행 중인 응용 프로그램 목록을 얻어오는데는 문제
가 없습니다. 위의 소스에서는 if문을 이용해서 작업관리자의 목록만을 가져
오지만 혹시나 모든 윈도우의 핸들이 필요하시다면 if문을 살짝 지우면 다 가
져 올 수 있겠지요...ㅎㅎ
IsWindowVisible 함수를 이용해서 윈도우의 WS_VISIBLE 속성이 On이면서
캡션의 길이가 0보다 큰 녀석들만 가져옵니다.
pDlg는 다이얼로그의 포인터이구요 컨트롤형 변수로 선언된 콤보박스에 CString
으로 선언된 HwndInfo를 AddString으로 넘겨주면 아래의 그림과 같이 작업
관리자와 똑같은 목록을 얻어 올 수가 있습니다.




[출처] http://frog3147.tistory.com/64

2008. 11. 19. 14:02

VC2005에서 VC6의 클래스 위자드 처럼 사용하기

VC2005에는 VC6과 같은 클래스 위자드가 없습니다. 그래서 다른 방법으로
클래스에 이벤트를 적용할 수 있습니다.

1. 클래스에서 마우스 오른쪽 속성을 선택합니다.

2. 속성창에서 "메세지" 툴박스를 선택합니다.

3. 원하는 이벤트를 추가/삭제/편집합니다.


4. 리소스 에디터에서 컴포넌트를 선택후 마우스 오른쪽으로 변수 추가를 선택

5. 변수에 관한 설정을 합니다.

그럼 클래스 위자드와 비슷하게 작업이 가능하게 됩니다.