全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:14091
推到 Plurk!
推到 Facebook!

UNICODE 轉 ANSI(BIG5)?

答題得分者是:Stallion
joana
一般會員


發表:35
回覆:70
積分:21
註冊:2005-09-02

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-06-11 23:04:23 IP:122.124.xxx.xxx 訂閱
我要從MS SQL2000 的 nvarchar 欄位中, 抓取資料,轉成ANSI(BIG5) ,轉完後再存入 varchar 之欄位
我有參考某位大德的function
//Unicode 轉 ANSI
function WideStringToString(const WS: WideString; CodePage: Word): string;
var InputLength, OutputLength: Integer;
begin
InputLength := Length(WS);
OutputLength := WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, nil, 0, nil, nil);
SetLength(Result, OutputLength);
WideCharToMultiByte(CodePage, 0, PWideChar(WS), InputLength, PChar(Result), OutputLength, nil, nil);
end;

procedure TForm1.BitBtn3Click(Sender: TObject);
var myws: WideString;
ws:string;
begin
ADOQuery1.first;
myws :=ADOQuery1['thd_mmrk']; //此欄位是 nvarchar
edit1.text:=WideStringToString(myws,950);

end;

myws 的內容是 "提供类似Adobe 公司的Photoshop, fireworks的图形处理功能。" ,經過轉換後
edit1.text 所顯示的內容卻是 " 提供?似Adobe 公司的Photoshop, fireworks的?形?理功能。"
不曉得有何地方弄錯,請有經驗之大德幫幫忙,謝謝!




Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-06-12 00:58:48 IP:211.22.xxx.xxx 未訂閱
1.你的函數使用WideCharToMultiByte試著將簡體轉換成繁體對嗎?查一下API,這個函數只是在做萬國碼與多位元字碼編碼的轉換而已,而不是在作簡繁轉換;另外你給的CODEPAGE參數也給錯了吧!查一下WINAPI。
2.你的文字資料編碼怎麼轉,使用一個不支援UNICODE的VCL元件,是沒辦法顯示正確語系文字的,採用支援萬國碼的VCL元件,並確認所使用的元件中字型的屬性使用支援萬國碼的字型檔即可。
3.如果你堅持要轉成繁體中文,先將你的Unicode簡體轉成多位元編碼後,再將相映的多位元簡體編碼轉成繁體編碼,這邊有個轉換的函數。那麼中文版下的Delphi內件VCL元件即可顯示。
編輯記錄
Stallion 重新編輯於 2007-06-12 01:20:17, 註解 無‧
joana
一般會員


發表:35
回覆:70
積分:21
註冊:2005-09-02

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-06-12 21:37:13 IP:122.124.xxx.xxx 訂閱
謝謝stallion大德的回覆,問題已解決了,果然再加上cvcode,就可轉成繁體
程式碼如下
uses cvcode;
procedure TForm1.BitBtn3Click(Sender: TObject);
var myws: WideString;
ws:string;
begin
ADOQuery1.first;

myws :=ADOQuery1['thd_mmrk'];
edit1.text:=GBToBIG5(WideStringToString(myws,936));

但問題來了,nvarchar欄位之內容,有時是簡体字,有時是繁體字,有時是英文, 簡体及英文用上面之程式可以正確轉換,但繁體經這麼一轉,就亂掉了,那怎麼判斷nvarchar欄位之內容是簡体或繁體?
再麻煩大德幫忙,感激不盡!

Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-06-12 21:50:14 IP:211.22.xxx.xxx 未訂閱
如果你的問題可以作,那麼萬國碼是多餘的!
當初就是因為各國字型編碼衝突,所以在不同的作業系統下才會衝碼,變成亂碼~
觀察你的敘述,你的資料庫本身裡面本身就已經是Unicode的資料了,可以省去資料庫內容轉換的問題,改用我之前所述的萬碼碼(Unicode)來作吧~
joana
一般會員


發表:35
回覆:70
積分:21
註冊:2005-09-02

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-06-12 22:08:49 IP:122.124.xxx.xxx 訂閱
謝謝大德的回覆,您建議採用支援萬國碼的VCL元件,但delphi 的元件並不支援UNICODE,除非用 
tnt Unicode Control,因這套程式只在台灣使用,且程式都已開發完畢,不可能再改用其他元件,所以才須如此麻煩,請大德再幫幫忙!
Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#6 引用回覆 回覆 發表時間:2007-06-12 22:13:03 IP:211.22.xxx.xxx 未訂閱
這裡有一篇歸木淡先進提供的資訊,應該可以用~
http://delphi.ktop.com.tw/board.php?cid=30&fid=76&tid=75030
===================引 用 joana 文 章===================
謝謝大德的回覆,您建議採用支援萬國碼的VCL元件,但delphi 的元件並不支援UNICODE,除非用
tnt Unicode Control,因這套程式只在台灣使用,且程式都已開發完畢,不可能再改用其他元件,所以才須如此麻煩,請大德再幫幫忙!
joana
一般會員


發表:35
回覆:70
積分:21
註冊:2005-09-02

發送簡訊給我
#7 引用回覆 回覆 發表時間:2007-06-12 22:57:48 IP:122.124.xxx.xxx 訂閱
剛試了一下,無論是簡体或繁體, IsBig5都 = true

unit strtoucode;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, Db, ADODB, ShellAPI,sub01;

const
AllowWindowsExtension=true; //Windows big5比標準big5多七個字和一些符
Min_SecondChar1 = #$40; Max_SecondChar1 = #$7E;
Min_SecondChar2 = #$A1; Max_SecondChar2 = #$FE;
Big5SecondChar = [Min_SecondChar1..Max_SecondChar1,
Min_SecondChar2..Max_SecondChar2];


type
TForm1 = class(TForm)
BitBtn1: TBitBtn;
ADOQuery1: TADOQuery;
DataSource1: TDataSource;
BitBtn2: TBitBtn;
BitBtn3: TBitBtn;
Edit1: TEdit;
BitBtn4: TBitBtn;
BitBtn5: TBitBtn;
Edit2: TEdit;
BitBtn6: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
procedure BitBtn4Click(Sender: TObject);
procedure BitBtn5Click(Sender: TObject);
procedure BitBtn6Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses cvcode;
{$R *.DFM}

function IsBig5(const S: string):Boolean; // Empty is NOT Big5
begin
result:=false;
If length(s)<2 then exit;
if not (S[2] in Big5SecondChar) then exit;
Case S[1] of
#$A1..#$A2,#$A4..#$C5,#$c9..#$F8: result:=true;
#$A3: result:=(s[2]<=#$BF) or ((s[2]=#$E1) and AllowWindowsExtension);
#$C6: result:=s[2]<=#$7E;
#$F9: result:=(s[2]<=#$D5) or AllowWindowsExtension;
end;

end;



procedure TForm1.BitBtn6Click(Sender: TObject);
begin
ADOQuery1.first;

if IsBig5(ADOQuery1['thd_mmrk']) then // ADOQuery1['thd_mmrk'] 內容是 "提供类似"
showmessage('big5')
else showmessage('not big5')

Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#8 引用回覆 回覆 發表時間:2007-06-12 23:19:58 IP:211.22.xxx.xxx 未訂閱
從上面的討論你沒發現嗎?你的資料庫內容本身是Unicode,你要利用這個函數判斷,先要將字串轉換成Multi-Byte String。
joana
一般會員


發表:35
回覆:70
積分:21
註冊:2005-09-02

發送簡訊給我
#9 引用回覆 回覆 發表時間:2007-06-12 23:47:41 IP:122.124.xxx.xxx 訂閱
嘻嘻,不好意思,請再提示一下,如何把字串轉換成Multi-Byte String?
因才剛接觸這類題目,所以比較不懂,又因時間急迫,請大德見諒!
謝謝您的熱心幫忙!
Stallion
版主


發表:52
回覆:1600
積分:1995
註冊:2004-09-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2007-06-13 00:48:09 IP:211.22.xxx.xxx 未訂閱
字串轉成Multi-Byte String不是在你原來的程式裡面就有了嗎?WideCharToMultiByte.
不過我覺得問題還是回到原點!使用上述的簡繁轉換需要是MultiByte字串,而在使用WideCharToMultiByte時必須知道要被轉換文字的Locale,而目前你的資料庫中的資料型態是Unicode簡繁混雜,目前的狀況就是無法知道某一筆將要處理的記錄裡面到底是簡體還是繁體,又因為記錄的型態是Unicode無法以簡繁函數來判斷,所以我覺得還是以Unicode的方式來處理。更或者看看站裡面的先進有沒有其他的辦法以Unicode來判定簡繁。
===================引 用 joana 文 章===================
嘻嘻,不好意思,請再提示一下,如何把字串轉換成Multi-Byte String?
因才剛接觸這類題目,所以比較不懂,又因時間急迫,請大德見諒!
謝謝您的熱心幫忙!
joana
一般會員


發表:35
回覆:70
積分:21
註冊:2005-09-02

發送簡訊給我
#11 引用回覆 回覆 發表時間:2007-06-13 09:58:57 IP:122.124.xxx.xxx 訂閱
謝謝stallion大德的回覆,如何以Unicode來判定簡繁,我會在查站內的資料,也謝謝您的熱心幫忙,
至少簡繁轉換已搞定,感恩不盡!
系統時間:2017-12-15 10:30:44
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!