【问题标题】:Delphi - Problem With Set String and PAnsiChar and Other Strings not DisplayingDelphi - 设置字符串和 PAnsiChar 以及其他字符串不显示的问题
【发布时间】:2023-03-19 00:13:02
【问题描述】:

我收到了advice from Rob Kennedy,他的一项建议是使用SetString,然后将其加载到显示它的 VCL 组件中,从而大大提高了我正在开发的应用程序的速度。

我使用的是 Delphi 2009,所以现在 PChar 是 Unicode,

SetString(OutputString, PChar(Output), OutputLength.Value);
edtString.Text := edtString.Text + OutputString;

有效,我自己将其更改为 PChar,但由于被移动的数据并不总是 Unicode,实际上它通常是 ShortString 数据....所以到他实际给我使用的内容:

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 并用 .这是我打算稍后做的事情来模拟十六进制编辑器样式。

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

【问题讨论】:

    标签: delphi string pointers char ansi


    【解决方案1】:

    一些cmets:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

      • 谢谢你看看这里是我正在处理的当前程序的截图 - klutsh.com/rain/PSPi05.PNG
      • RawByteString 总是有一个与之关联的代码页,只是不像其他基于 AnsiString 的字符串类型那样可以在编译时指定。将 UnicodeString 分配给 RawByteString,或将 RawByteString 分配给任何其他基于 AnsiString 的字符串类型,将始终使用字符有效负载中实际指定的任何代码页执行字符串转换。
      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-01
        • 2010-09-21
        • 1970-01-01
        • 2011-06-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多