1

我从 Rob Kennedy那里得到了建议,他的一个建议是,他的建议之一是使用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,但没有显示任何内容。我还发现有趣的是,当我将我的十六进制数据从同一个数组构建到 Richedit 中时,它非常快,而在文本数据的编辑中执行它非常非常慢。这就是为什么我没有费心尝试更改richedit 的代码,因为它的运行速度非常快。

编辑添加 - 我想我找到了问题,但我没有解决方案。如果我在调试器中编辑值以删除任何无法显示的内容(旧方法过去只是不显示......不会失败),那么我剩下的就会显示出来。因此,如果只是摆脱被转换为垃圾字符的字节的问题,我该如何解决呢?

我基本上从正在显示十六进制编辑器样式的 SCSI 设备传入原始数据。我最初一次添加一个字符的慢速风格成功地显示了字符串和其中没有 Unicode 特定字符的 Unicode 字符串。更快的方法即使工作也不会以一种方式显示 ShortStrings,而另一种方式不会显示不使用非 0-255 字符的 UnicodeStrings。我真的很喜欢并且可以使用速度提升,但如果这意味着牺牲读取字符串的能力......那么应用程序的意义何在?

EDIT3 - 好吧,现在我已经发现 0-31 是控制字符并且 32 及以上是有效的,我想我会尝试过滤 char 并将那些无效的替换为 . 这是我打算稍后做的事情来模拟十六进制编辑器样式。

如果有任何其他建议,我很乐意听到它们,但除此之外,我认为我可以制定一个比原始解决方案更快的解决方案,同时满足我的需要。

4

3 回答 3

3

一些评论:

  1. 你的问题很不清楚。你到底想做什么?
  2. 您的问题读起来很糟糕,请使用拼写检查器检查您的文字。
  3. 您所指的问题是:Delphi access data from dynamic array that is paid from an untyped pointer
  4. 请像您在上一个问题中所做的那样提供您的函数的完整代码示例,我想知道您是否实施了 Rob Kennedy 的建议或您在以下答案中给自己的代码(希望不是 :))
  5. 据我了解您的问题:您正在向您的 SCSI 设备发送查询,并且您得到一个字节数组,您将其存储在变量 OutputData 中。之后,您想向用户显示您的数据。所以你真正的问题是:如何向用户显示一个字节数组?
  6. 以同一用户身份登录,不要为每个新问题创建一个帐户。这样我们就可以跟踪您的问题历史,并通过“获得建议”了解您的意思。

如果我对您问题的真正含义是正确的,一些假设和建议:

  1. 将您的数据显示为十六进制字符串不会有任何问题
  2. 在普通的备忘录字段中显示数据会给您带来问题,尽管 Delphi 字符串可以包含任何字符,包括 0 个字节,但显示它们会给您带来问题。例如,一个 TMemo 将显示您的数据,直到第一个 0 字节。您必须做的(并且您自己给出了答案)是用假人替换不可见的字符。之后,您可以在 TMemo 中显示您的数据。实际上所有十六进制查看器都这样做,无法打印的字符将显示为一个点。
于 2009-03-13T08:31:59.983 回答
1

PAnsiChar在我的例子中使用是有原因的。它看起来OutputLength是以字节而不是字符来衡量的,所以我确保使用长度总是以字节为单位的类型。你还会注意到我展示了OutputStringas 的声明AnsiString

AnsiString但是,由于编辑控件存储了 Unicode,因此和之间会有转换UnicodeString。这将考虑系统的当前代码页,但这可能不是您想要的。您可能希望将变量声明为 a RawByteString。这不会有任何与之关联的代码页,因此不会有任何意外的转换。

不要使用字符串来存储二进制数据。如果您正在构建相当于十六进制编辑器的内容,那么您正在使用二进制数据。记住这一点很重要。即使您的二进制数据碰巧主要由可以解释为文本的字节组成,您也不能将数据视为文本,否则您将遇到您所看到的问题——未按预期显示的字符。如果您从 SCSI 设备获得一堆字节,则将它们存储在字节数组中,而不是字符。

在十六进制编辑器中,您会注意到它们始终显示字节的十六进制值。它们可能会显示那些解释为字符的字节,但这是次要的,它们通常只显示可以表示 ASCII 字符的字节;他们不会尝试对基本显示器过于花哨。好的十六进制编辑器也可以将解释为宽字符的数据显示出来。这有助于调试,因为用户可以通过多种方式查看相同的数据。但它们只是对数据的看法。它们实际上并没有改变数据的二进制内容。

于 2009-03-13T18:27:15.170 回答
0

当您过滤掉不可见的字符时...您可能需要决定如何处理其中的几个,例如#9(Tab)、#10(LF)、#11(Verticle Tab)、#12(FF-或新页),#13(CR)

于 2009-03-13T13:46:35.890 回答