6

Delphi 6で開発されたポーリングアプリケーションがあります。ファイルを読み取り、仕様に従ってファイルを解析し、検証を実行してデータベースにアップロードします(SQL Server 2008 Express Edition

日本語 OS などの 2 バイト文字セット (DBCS) を持つオペレーティング システムのサポートを提供する必要がありました。そこで、SQL Server のデータベース フィールドを varchar から nvarchar に変更しました。

ポーリングは、DBCS を使用するオペレーティング システムで正常に機能します。システム ロケールが日本語/中国語/韓国語に設定されていて、オペレーティング システムにそれぞれの言語パックがある場合、DBCS 以外のオペレーティング システムでも正常に機能します。ただし、ロケールが英語に設定されている場合、データベースには 2 バイト文字のジャンク文字が含まれます。

いくつかのテストを実行しましたが、解決策を特定できませんでした。

たとえば、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 オペレーティング システムで正常に動作します。

文字列、ワイド文字列、UTF8文字列で遊んでみました。ただし、ロケールが英語に設定されている場合、これは英語 OS では機能しません。

この問題に関する指針を提供してください。

4

2 に答える 2

4

非 Unicode Delphi バージョンでは、基本はs (Ansi)WideStringではなく s (Unicode) で作業する必要があるということです。String

TADOQuery.SQL(TStrings) を忘れて、 TADODataSet.CommandTextor TADOCommand.CommandText(WideString) または typecast TADOQueryasで作業します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.ParseSQLis Ansi. ParamChecktrue (デフォルト) の場合TADOCommand.SetCommandText->AssignCommandTextクエリが Unicode ( InitParametersAnsi) の場合、問題が発生します。

Command.Parameters(ADOを直接使用できることに注意してください?。Delphi の規則ではなく、パラメータのプレースホルダーとして chars を使用します:param_name)。


QuotedStrAnsi 文字列を返します。この関数の Wide バージョンが必要です (TNT)


また、@Arioch 'として言及されたTNT Unicode Controlsスイートは、Delphi Unicode アプリケーションを作成するための最良の揚げ物です。アプリケーションで Unicode タスクを適切に管理するために必要なすべてのコントロールとクラスが含まれています。

要するに、ワイドに考える必要があります:)

于 2013-01-10T11:56:00.330 に答える
3
  1. あなたはデータベースサーバーを指定しなかったので、この調査は私たちの側に残ります。データベースサーバーがUnicodeをどのようにサポートしているかを確認する必要があります。これは、データベースとその中のテーブル/列/インデックス/照合などにUnicode文字セットを指定する方法を意味します。データの損失を防ぐために、DB全体が細部にわたってUnicode対応になっていることを確認する必要があります。

  2. 通常、データベース接続(選択したデータベースアクセスライブラリを使用)もUnicode対応であることを確認する必要があります。一般に、Microsoft ADOは、OLEと同様に、Unicode対応である必要があります。ただし、接続文字列でUnicodeコードページまたは文字セットを指定する方法については、データベースサーバーのマニュアルを確認してください。Unicode以外の接続でも、データが失われる可能性があります。

  3. あなたがいくつかのユニコードファイルを読むと言うとき-それは曖昧です。どのiusユニコードファイルですか?UTF-8ですか?または、UTF-16の4つのフレーバーの1つですか?またはUTF-7?または他のUnicodeトランスポーテーションフォーマット?通常のウィンドウWideCharは、レガシーUCS-2にほぼ対応しており、UTF-16のBOMを取り除いたIntel-Endianフレーバーであると予想されます。 http://msdn.microsoft.com/en-us/library/windows/desktop/ms221069.aspx

  4. ファイルが確かにUTF-16のフレーバーである場合は、DelphiTWideStringListまたはJediCodeLibraryを使用してファイルをロードできますTJclWideStringList。文字列変数を使用してデータを操作することは決してないというコードを確認してください。データの損失を避けるために、どこでもWideStringを使用してください。
    D6は最もバグの多いリリースの1つだったので、Delphiのすべての更新プログラムがインストールされていることを確認してから、JCLをインストールして使用したいと思います。AnsiStringVar := WideStringVarJCLは、コードページ遷移関数も提供します。これは、単純なアプローチよりも柔軟な場合があります。UTF-8ファイルの場合、JCLのクラスごと
    にロードできます(ただし、ロードできません)。TWideStringListTJclWideStringList

  5. デバッグ時に、リストの行をWideString変数にロードし、それらのコンテンツが保持されていることを確認します。

  6. そのようなクエリを書かないでください。http://bobby-tables.com/を参照してください。悪意のあるクラッカーを予期していなくても、エラーを作成したり、予期しないデータを作成したりする可能性があります。いつでも、どこでも、パラメータ化されたクエリを使用してください!これまで!
    そのような例を参照してください。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に対応していないため、無料バージョンを見つけたり購入したりできる場合は、アプリケーションをTNTUnicodeコンポーネントに移行することを検討してください。または、新しいDelphiリリースに移行します。

    7.3。Delphi 6は非常に古く、長い間サポートされておらず、最もバグの多いDelphiリリースの1つであったため、新しいDelphiバージョンまたはCodeTyphoonやLazarusなどの無料ツールへの移行を検討してください。ボーナスとして、Lazarusは最近のベータビルドでUnicodeへの移行を開始しました。移行が終了するまでに、アプリケーションをUnicode対応にすることができます。

    7.4移行は、アプリケーションをリファクタリングし、レガシースパゲッティを取り除くための言い訳と刺激になる可能性があります。

于 2013-01-10T08:54:58.987 に答える