簡體   English   中英

使用Delphi 6處理Unicode字符

[英]Handling of Unicode Characters using Delphi 6

我有一個在Delphi 6中開發的輪詢應用程序。它讀取文件,根據規范解析文件,執行驗證並上傳到數據庫( SQL Server 2008 Express Edition

我們必須為具有雙字節字符集(DBCS)的操作系統提供支持,例如日語操作系統。 因此,我們將SQL Server中的數據庫字段從varchar更改為nvarchar。

輪詢在使用DBCS的操作系統中工作正常。 如果系統區域設置設置為日語/中文/韓語且操作系統具有相應的語言包,則它也可以成功用於非DBCS操作系統。 但是,如果Locale設置為english,則數據庫包含雙字節字符的垃圾字符。

我進行了一些測試但未能確定解決方案。

例如,如果我使用TStringList從UTF-8文件讀取並將其保存到另一個文件,則保存Unicode數據。 但是,如果我使用該文件的內容使用TADOQuery組件運行更新查詢,則會顯示垃圾字符。 該數據庫還包含垃圾字符。

PFB示例代碼:

var
    stlTemp : TStringList;
    qry : TADOQuery;
    stQuery : string;
begin
    stlTemp := TStringList.Create;
    qry := TADOQuery.Create(nil);
    stlTemp.LoadFromFile('D:\DelphiUnicode\unicode.txt');
    //stlTemp.SaveToFile('D:\DelphiUnicode\1.txt'); // This works. Even though 
    //the stlTemp.Strings[0] contains junk characters if seen in watch

    stQuery := 'UPDATE dbo.receivers SET company = ' + QuotedStr(stlTemp.Strings[0]) +
        ' WHERE receiver_cd = N' + QuotedStr('Receiver'); 
    //company is a nvarchar field in the  database
    qry.Connection := ADOConnection1;
    with qry do
    begin
        Close;
        SQL.Clear;
        SQL.Add(stQuery);
        ExecSQL;
    end;
    qry.Free;
    stlTemp.Free
end;

以上代碼在DBCS操作系統中正常工作。

我嘗試過使用string,widestring和UTF8String。 但是,如果語言環境設置為英語,則在英語操作系統中不起作用。

請提供此問題的任何指示。

  1. 您沒有指定數據庫服務器,因此我們仍在進行此調查。 您應該檢查數據庫服務器如何支持Unicode。 這意味着如何為數據庫和其中的tables / column / indices / collat​​ions / etc指定Unicode charset。 您必須確保整個數據庫在其每個細節中都具有普遍的Unicode功能,以避免數據丟失。

  2. 通常,您還應該檢查您的數據庫連接(使用選擇的數據庫訪問庫)是否也啟用了unicode。 通常Microsoft ADO,就像和OLE一樣,應該啟用Unicode。 但仍然檢查數據庫服務器手冊如何在連接字符串中指定unicode代碼頁或字符集。 非Unicode連接也可能導致數據丟失。

  3. 當你告訴你讀一些unicode文件時 - 它是模棱兩可的。 什么ius unicode文件? 是UTF-8嗎? 或者四種UTF-16中的一種? 還是UTF-7? 或者其他一些Unicode傳輸格式? 通常的Windows WideChar大致對應於傳統的UCS-2,預計將采用BOM剝離的Intel-Endian風格的UTF-16。 http://msdn.microsoft.com/en-us/library/windows/desktop/ms221069.aspx

  4. 如果文件肯定是UTF-16的味道,那么你可以使用Delphi TWideStringList或Jedi CodeLibrary TJclWideStringList加載它。 查看您從未使用字符串變量處理數據的代碼 - 在任何地方使用WideString以避免數據丟失。
    由於D6是最糟糕的版本之一,我寧願確保安裝了Delphi的每個更新,然后安裝並使用JCL。 JCL還提供代碼頁轉換功能,這可能比普通的AnsiStringVar := WideStringVar方法更靈活。
    對於UTF-8的文件,它可以通過加載TWideStringList類JCL(但不是TJclWideStringList )。

  5. 調試時,將列表的行加載到WideString變量,並查看其內容是否已保留。

  6. 不要寫那樣的查詢。 請參閱http://bobby-tables.com/即使您不期望惡意破解者 - 您也可以自己制造錯誤或出現意外數據。 每次都在任何地方使用參數化查詢! EVER!
    請參閱以下示例: http//docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/ADODB_TADOQuery_Parameters.html
    檢查每個SQL VARCHAR參數是否為ftWideString以包含Unicode,而不是ftString 檢查字段(列)的相同內容。

  7. 想想遺留技術是否可以放在一邊,因為他們的支持只會越來越難以及時。

    7.1。 由於Microsoft ADO已棄用(例如,對於較新版本的Microsoft SQL Server不支持),請考慮切換到“實時”數據訪問庫。 像AnyDAC,UniDAC,ZeosDB或其他一些庫。 Torry.net可能會暗示你一些。

    7.2。 由於Delphi 6 RTL和VCL不支持Unicode,因此如果您設法找到他們的免費版本或購買它們,請考慮將您的應用程序遷移到TNT Unicode組件。 或者遷移到更新的Delphi版本。

    7.3。 由於Delphi 6非常陳舊且長期不受支持,並且因為它是最糟糕的Delphi版本之一,所以請考慮遷移到較新的Delphi版本或CodeTyphoon或Lazarus等免費工具。 作為獎勵,Lazarus在其最近的beta版本中開始轉向Unicode,並且有可能在遷移結束時,您將獲得應用程序unicode就緒。

    7.4遷移可能是重新考慮您的應用程序和擺脫傳統意大利面條的借口和刺激因素。

在非Unicode Delphi版本中,基礎是您需要使用WideString (Unicode)而不是String (Ansi)。

忘記TADOQuery.SQL (TStrings),並使用TADODataSet.CommandTextTADOCommand.CommandText (WideString)或類型轉換TADOQuery作為TADODataSet 例如:

stlTemp: TWideStringList; // <- Unicode strings - TNT or other Unicode lib
qry: TADOQuery;
stQuery: WideString; // <- Unicode string

TADODataSet(qry).CommandText := stQuery;
RowsAffected := qry.ExecSQL;

您還可以使用TADOConnection.Execute(stQuery)直接執行查詢。


使用參數化查詢時要格外小心: ADODB.TParameters.ParseSQL是Ansi。 如果ParamCheck為true(默認情況下) TADOCommand.SetCommandText - > AssignCommandText將導致問題,如果您的Query是Unicode( InitParameters是Ansi)。

(請注意,您可以直接使用ADO Command.Parameters - 使用? chars作為參數的占位符而不是Delphi的約定:param_name )。


QuotedStr返回Ansi字符串。 你需要這個功能的寬版本(TNT)


此外,作為@Arioch'提到的TNT Unicode Controls套件是您最好的制作Delphi Unicode應用程序。 它具有在應用程序中成功管理Unicode任務所需的所有控件和類。

總之,你需要思考 :)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM