Delphi-Set StringとPAnsiCharおよびその他の文字列が表示されない問題
質問
Rob Kennedyのアドバイスと、作業中のアプリの速度を大幅に向上させた彼の提案の1つは、 SetString
を使用して、表示されるVCLコンポーネントに読み込むことでした。それ。
Delphi 2009を使用しているため、PCharがUnicodeになりました
SetString(OutputString, PChar(Output), OutputLength.Value);
edtString.Text := edtString.Text + OutputString;
私はそれを自分でPCharに変更しましたが、移動されるデータは実際には常にUnicodeではないので、通常はShortString Data ....ということで、彼が実際に使用してくれたものについて:
SetString(OutputString, PAnsiChar(Output), OutputLength.Value);
edtString.Text := edtString.Text + OutputString;
何も表示されませんが、デバッガーでチェックインすると、通常は過去に一度に1文字ずつビルドしたときに表示されるテキストが変数に含まれていました。
奇妙なことに、これが私がこの夜に出会ったのは初めてではありません。私は別の方法を考え出そうとしていたので、私は彼のアドバイスに参加し、VCLのTCaptionに組み込む代わりに、文字列変数に組み込み、それをコピーしましたが、何も表示せずに送信すると、デバッガーでもう一度、データが組み込まれている変数にデータがあります。
for I := 0 to OutputLength.Value - 1 do
begin
OutputString := OutputString + Char(OutputData^[I]);
end;
edtString.Text := OutputString;
上記は機能しませんが、それを行う古い低速の方法はうまく機能しました。...
for I := 0 to OutputLength.Value - 1 do
begin
edtString.Text := edtString.Text + Char(OutputData^[I]);
end;
変数をShortString、String、およびTCaptionにしようとしましたが、何も表示されません。また、同じ配列の16進データをリッチエディットに構築するのは非常に高速ですが、テキストデータの編集内で実行するのは非常に低速です。リッチエディットのコードを変更しようとして気にしなかった理由は、それがそのまま超高速で動作するからです。
追加して編集-問題を見つけたと思いますが、解決策はありません。デバッガーで値を編集して、表示できないもの(古い方法では表示されない...失敗しないもの)を削除すると、残っているものが表示されます。ガベージな文字に変換されたバイトを取り除くだけの場合は、どうすれば修正できますか?
基本的に、16進エディタースタイルで表示されているSCSIデバイスから受信した生データがあります。一度に1つの文字を追加する元のスロースタイルでは、文字列とUnicode固有の文字が含まれていないUnicode文字列が正常に表示されました。動作が速い場合でも、片方のメソッドではShortStringが表示されず、もう一方の方法では0〜255以外の文字を使用していないUnicodeStringが表示されません。スピードブーストは本当に気に入って使用できますが、文字列を読み取る機能を犠牲にすることを意味する場合は、アプリのポイントは何ですか?
EDIT3-0〜31が制御文字であり、32以上が有効であることがわかったので、文字をフィルタリングし、無効な文字をに置き換えようとすると思います。これは、16進エディタースタイルをエミュレートするために後で行うことを計画していたものです。
他に提案がある場合は喜んでお聞きしますが、そうでない場合は、オリジナルよりも高速で、必要なことを同時に実行できるソリューションを作成できると思います。
解決
この例では、理由により PAnsiChar
を使用しました。 OutputLength
は文字ではなくバイトで測定されているように見えたので、長さが常にバイトで測定される型を使用するようにしました。また、 AnsiString
として OutputString
の宣言を示したことがわかります。
ただし、エディットコントロールにはUnicodeが格納されているため、 AnsiString
と UnicodeString
の間で変換が行われます。それはシステムの現在のコードページを考慮に入れますが、それはおそらくあなたが望むものではありません。代わりに、変数を RawByteString
として宣言することをお勧めします。コードページは関連付けられていないため、予期しない変換は発生しません。
バイナリデータの格納に文字列を使用しないでください。 16進エディタに相当するものを構築している場合、バイナリデータを使用しています。それを覚えておくことは重要です。バイナリデータがほとんどテキストとして解釈できるバイトで構成されている場合でも、そのデータをテキストとして扱うことはできません。 ;期待どおりに表示されない文字。 SCSIデバイスから大量のバイトを取得した場合は、文字ではなくバイトの配列に保存します。
16進エディタでは、バイトの16進値が常に表示されることがわかります。それらは文字として解釈されるバイトを表示するかもしれませんが、それは二次的なものであり、通常はASCII文字を表現できるバイトのみを表示します。彼らは基本的なディスプレイにあまり凝りこもうとしない。 good 16進エディタも、ワイド文字として解釈されるデータを表示するように提案します。ユーザーは同じデータを複数の方法で見ることができるため、これはデバッグに役立ちます。しかし、それらはデータの単なるビューです。実際には、データのバイナリコンテンツを変更するわけではありません。
他のヒント
コメント:
- あなたの質問は非常に不明瞭です。正確に何をしたいですか?
- あなたの質問はひどいものです。スペルチェッカーでテキストを確認してください。
- あなたが言及している質問はこれです: Delphiは、型なしポインターから入力された動的配列からデータにアクセスします
- 前の質問で行ったように関数の完全なコードサンプルを提供してください。RobKennedyの提案を実装したか、次の答えで自分で与えたコードを実装したかどうかを知りたいです。 >
- 私があなたの質問を理解している限り:あなたはSCSIデバイスにクエリを送信していて、変数OutputDataに格納するバイトの配列を取得しています。その後、ユーザーにデータを表示します。あなたの本当の質問は次のとおりです。ユーザーにバイトの配列を表示する方法
- 同じユーザーとしてログインし、新しい質問ごとにアカウントを作成しないでください。そうすることで、質問履歴を追跡し、「アドバイスを得る」ことであなたが何を意味するかを知ることができます。
あなたの質問の本当の意味が正しい場合、いくつかの仮定と提案:
- データを16進文字列として表示しても問題はありません
- 通常のメモフィールドにデータを表示すると問題が発生しますが、Delphiの文字列には0バイトを含む任意の文字を含めることができますが、表示すると問題が発生します。たとえば、TMemoは最初の0バイトまでデータを表示します。あなたがしなければならない(そしてあなた自身が答えを与えた)ことは、見えない文字をダミーに置き換えることです。その後、TMemoでデータを表示できます。実際、すべての16進ビューアは同じことを行い、印刷できない文字はドットとして表示されます。
表示できない文字を除外する場合は、おそらく#9(Tab)、#10(LF)、#11(Verticle Tab)、#12のようないくつかの文字をどうするかを決定する必要があります。 (FFまたは新しいページ)、#13(CR)