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

XE7 FireDAC FireBird Blob UTF8

 
pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#1 引用回覆 回覆 發表時間:2014-09-19 09:14:47 IP:120.236.xxx.xxx 訂閱
DELPHI 从有 DBExpress 以来,一直到 XE6,如果用 DBExpress 连接 FireBird 数据库,而数据库的 CharSet 是 UTF8 的话,其中的 Blob 用 DBMemo 来做用户界面,按照以下方式处理:

FireBird -- SQLConnection -- SQLDataSet -- DataSetProvider -- ClientDataSet -- DataSource -- DBMemo

如果用 UTF8 ,那么中文直接输入到 DBMemo 里面,提交到 DataBase 里面去,下次再打开,DBMemo 里面显示的是乱码。

现在 XE7 带来了 FireDAC,我测试,如果把 DBExpress 的 SQLConnection 和 SQLDataSet 替换为 FireDAC 的元件,这个问题解决了。

对 FireDAC 和 FireBird 的进一步测试,发现:

1. 搜索 UTF8 VarChar 字段,用 like 语句,可以正确搜索;
2. 搜索 UTF8 Blob 字段,用 like 语句,可以正确搜索;


所以,如果做正式产品,之前DELPHI推荐的 DBExpress 应该换成 FireDAC 了。
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#2 引用回覆 回覆 發表時間:2014-09-19 15:46:28 IP:220.136.xxx.xxx 未訂閱
哦! 真的嗎? xe6前我儲存dbmemo (FireBird 2.1x), 確實都還是亂碼, 只好改用 Tmemo 再經由轉換來顯示, 
那我得趕緊來試試看, 是否直接 dbmemo 都沒有問題了!
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2014-09-20 22:32:50 IP:118.160.xxx.xxx 未訂閱
個人實測的部份

系統部份
FireBird 2.11 Blob Field Win7 x64 XE7

Server端
DataSnap FireDAC (DataSetProvidor FBdriver FDconnection FDQuery)

app端(Android)
FireDAC (SQLconnection DSprovidorconnect ClientDataSet)

由手機端直接連接 Server端, 並由手機端app存入資料到server端
中文的部份(TwoBytes) 與 XE6 一樣還是亂碼
(透過 DBMemo 直接查看)
pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2014-09-23 12:05:54 IP:120.236.xxx.xxx 訂閱
目前我的测试代码是 RUN 在 XP 上的,没有乱码问题。但如果用 DBExpress 去连接 FireBird 则会有乱码。之前我的解决办法也是自己解码,用 TMemo 去显示。现在直接用 DBMemo 可以显示了。
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#5 引用回覆 回覆 發表時間:2014-09-24 09:38:59 IP:59.120.xxx.xxx 未訂閱
如果我在server端的 pc app直接進行 dbmemo 的編輯及顯示, dbmemo 是可以完整顯示 unicode 內容, 
可能是 在 fm2 的 ClientDataSet 與 server DataSnap 在處理 dbmemo 上沒有辦法直接轉碼吧! 我猜!
所以還是只能用 Memo (pc端) 轉碼 dbMemo 內容後才能正常顯示
===================引 用 pcplayer99 文 章===================
目前我的测试代码是 RUN 在 XP 上的,没有乱码问题。但如果用 DBExpress 去连接 FireBird 则会有乱码。之前我的解决办法也是自己解码,用 TMemo 去显示。现在直接用 DBMemo 可以显示了。
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2014-09-24 12:05:22 IP:59.120.xxx.xxx 未訂閱
我想了解一下你們的 Firebird 的 Blob 設定
以及 dbExpress driver 用的是哪一家的?

我目前用的是 dbExpress Driver for Firebird
以下是我的 DB code
/******************************************************************************/
/*** Generated by IBExpert 2010.03.19 2014/09/24 上午 11:56:28 ***/
/******************************************************************************/
SET SQL DIALECT 3;
SET NAMES UTF8;
SET CLIENTLIB 'D:\DBX棒棒\fbembed.dll';

CREATE DATABASE 'D:\DBX棒棒\TestUTF8.fdb'
USER 'DBX' PASSWORD 'LIKEDBX'
PAGE_SIZE 16384
DEFAULT CHARACTER SET UTF8;

/******************************************************************************/
/*** Tables ***/
/******************************************************************************/
CREATE TABLE NEW_TABLE (
A1 INTEGER NOT NULL,
A2 BLOB SUB_TYPE 0 SEGMENT SIZE 80,
A3 VARCHAR(50),
A4 BLOB SUB_TYPE 1 SEGMENT SIZE 16384
);
/******************************************************************************/
/*** Primary Keys ***/
/******************************************************************************/
ALTER TABLE NEW_TABLE ADD CONSTRAINT PK_NEW_TABLE PRIMARY KEY (A1);

Delphi 2009 擷圖


我想應該是差在 BLOB SUB_TYPE 設定而已吧


可以再多測試一下嗎?
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#7 引用回覆 回覆 發表時間:2014-09-24 14:23:53 IP:112.78.xxx.xxx 未訂閱
不好意思, 這篇是James 發表的, 變成討論

我按RuRu做法, 把 Blob 定義為 sub_type 0 (原本資料庫 blob 沒有定義任何型態), 重建了一個資料庫

然後一樣由 app 直接存取 後端 DataSnap server 資料, 資料庫仍為 FireBird 2.11 32bit

出來的結果就如以下圖片



GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2014-09-24 15:06:49 IP:59.120.xxx.xxx 未訂閱
不寫預設是 0

有試試看 SUB_TYPE 1 嗎?
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#9 引用回覆 回覆 發表時間:2014-09-24 23:38:58 IP:59.120.xxx.xxx 未訂閱
試過 0,1,2,3,4 ... 都不行, 反而更亂, 只有 0 還可以接受一些
另外有一種 sub_type text 也試過, 一樣亂
但我前面有強調, 如果是在pc端操作(不透過 DataSnap 運轉)是沒有問題,
有問題的是, 手機(ClientDataSet) 後端(DataSnap FireDAC)會出現這樣的情況
不管 blob 怎麼去定義或完全不定義
GrandRURU
站務副站長


發表:240
回覆:1680
積分:1874
註冊:2005-06-21

發送簡訊給我
#10 引用回覆 回覆 發表時間:2014-09-25 10:22:45 IP:59.120.xxx.xxx 未訂閱
看來 FireBird 的 Driver 還是有些問題

我這邊收集了一些解決方法:
不論 Firebird Blob 欄位的 sup_type 是 0 還是 1 (只有 0 / 1 / 2,2 是 Firebird 資料庫內專用,程式只能使用 0 和 1 )
寫入 Blob:
Sender.AsBytes := TEncoding.UTF8.GetBytes(ENCODE_STRING);

讀取 Blob:
Text := TEncoding.UTF8.GetString(CDS.Fields[1].AsBytes);

查詢:
SQLQuery1.Params.Items[0].AsBlob := TEncoding.UTF8.GetBytes(STRING);

===================引 用 P.D. 文 章===================
試過 0,1,2,3,4 ... 都不行, 反而更亂, 只有 0 還可以接受一些
另外有一種 sub_type text 也試過, 一樣亂
但我前面有強調, 如果是在pc端操作(不透過 DataSnap 運轉)是沒有問題,
有問題的是, 手機(ClientDataSet) 後端(DataSnap FireDAC)會出現這樣的情況
不管 blob 怎麼去定義或完全不定義
pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#11 引用回覆 回覆 發表時間:2014-09-25 18:52:30 IP:120.236.xxx.xxx 訂閱
以下是我几年前的测试结果记录:
用 IBDataBase IBTable 来连接 FireBird 2.1 的有 UTF8 字段的数据库。
IBDataBase.Params 如下:
user_name=sysdba
password=masterkey
lc_ctype=UTF8
如果不写 lc_ctype=UTF8 则返回来的是乱码。
DBGrid, DBMemo 指向 DataSource1。
1. 如果 DataSource1 指向 IBTable,则可以正常显示汉字,也能正常输入汉字并保存。保存后重新打开程序能看到保存结果正常。
2. 如果用 DBGrid/DBMemo -> DataSource -> ClientDataSet -> DataSetProvider -> IBTable,则打开表显示汉字正确。但如果修改 DBMEMO 的内容然后提交,保存到数据库里的内容是错误的。再次加载就能显示错误内容。
3. ClientDataSet 连接到 IBTable 时,设计期创建的字段,varchar 对应 TWideStringField,Blob字段对应的是 TMemoField,但此时 DBMEMO显示乱码;手动在设计期把该字段改为 TWideMemoField 则显示正确。
4. 如果用 DBExpress 去连接 FB,ClientDataSet 指向 SQLDataSet,则 DBMemo 里面显示乱码。但输入的汉字提交后保存到数据库是正确的。只是重新加载的时候显示乱码。这些提交的内容如果用 IBTable 来看是正确的。
5. 如果不用 ClientDataSet,直接将 DBGrid/DBMemo 连接到 IBTable,输入、输出的汉字都正常。
===========
从 fb 官网下载 ODBC 驱动安装后,用 ADOConnection ADODataSet,发现 BLOB 对应的 DBMEMO 里面全是显示乱码。看来这条路走不通。
============
DELPHI XE3 底下,从 BLOB 字段获取到的数据要正确显示,必须这样:
procedure TForm1.Button3Click(Sender: TObject);
var
B: TBytes;
begin
B := DataModule2.CldUserID.FieldByName('Info').AsBytes;
Memo1.Lines.Add(TEncoding.UTF8.GetString(B, 0, Length(B)));
end;
也就是说,对 UTF8 的 BLOB字段,Field.AsString 返回不了正确的字符串,必须自己解码。但是,DataModule2.CldUserID.FieldByName('INfo').AsString := Memo1.Lines.Text; 是可以将字符串正确保存进UTF8 的 BLOB 字段的。
关于这个问题,我有在 https://forums.codegear.com/message.jspa?messageID=557466#557466 提交。也有在DELPHI的质量中心提交。



=========================================================

总之,如果用 DBExpress 去连接 FireBird 然后通过 TClientDataSet 把数据给 TDBMemo ,UTF8 的 BLOB 就会出乱码。

但如果改用 FireDAC 就没事了。

我的测试环境有2种,一种是在一个 Program 里面,DBExpress(SQLConnection, -- SQLDataSet) --- DataSetProvider --- ClientDataSet --- DBMemo ,其中 DBExpress 的 FireBird driver 是 Delphi 自己带的,没用第三方的。
另一种是 DBExpress - DataSetProvider -- WebService ---- HTTPRIO or SOAPConnection -- ClientDataSet -- DBMemo 这里的 Client 也是 RUN 在 XP 上的,不是手机。

以上两种方式测试,都会乱码。

以上两种方式,只要把 DBExpress 替换为 FireDAC,就一切正常了。
P.D.
版主


發表:603
回覆:4038
積分:3874
註冊:2006-10-31

發送簡訊給我
#12 引用回覆 回覆 發表時間:2014-09-25 22:53:30 IP:59.120.xxx.xxx 未訂閱
期待 XE8 可以看到改善
系統時間:2024-04-26 0:40:41
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!