Delphi -设置字符串和PAnsiChar以及其他字符串未显示的问题

bybem2ql  于 2023-04-05  发布在  其他
关注(0)|答案(3)|浏览(255)

我从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。我真的很喜欢并且可以使用速度提升,但如果这意味着牺牲读取字符串的能力......那么应用程序的重点是什么?
EDIT 3-好了,现在我已经弄清楚了0-31是控制字符,32和32以上是有效的,我想我会尝试过滤字符,并用a替换那些无效的字符,这是我计划稍后模拟十六进制编辑器风格的事情。
如果有任何其他的建议,我会很高兴听到他们,但除此之外,我认为我可以工艺的解决方案,比原来的更快,并做我需要它在同一时间。

idfiyjo8

idfiyjo81#

一些评论:
1.你的问题很不清楚,你到底想做什么?
1.你的问题读起来很糟糕,请用拼写检查器检查你的文本。
1.你所指的问题是这样的:Delphi accessing data from dynamic array that is populated from an untyped pointer
1.请给予一个完整的代码示例,就像你在上一个问题中所做的那样,我想知道你是否实现了Rob Kennedy的建议或你在下面的答案中给自己的代码(希望不是:)
1.我理解你的问题:你发送一个查询到你的SCSI设备,你得到一个字节数组,你把它存储在变量OutputData中。之后你想把你的数据显示给用户。所以你真实的的问题是:如何向用户显示字节数组?
1.以同一个用户登录,不要为每个新问题创建一个帐户。这样我们就可以跟踪您的问题历史记录,并可以了解您所说的“获取建议”是什么意思。
一些假设和建议,如果我对你的问题的真正含义是正确的:
1.将数据显示为十六进制字符串不会给予任何问题
1.在一个普通的Memo字段中显示你的数据会给你带来问题,尽管 Delphi 字符串可以包含任何字符,包括0字节,显示它们会给你带来问题。例如,TMemo将显示你的数据直到第一个0字节。你必须做什么(你自己也给出了答案)是用一个虚拟字符替换不可见的字符。之后你可以在TMemo中显示你的数据。实际上所有十六进制查看器都是这样做的,不能打印的字符将显示为一个点。

kb5ga3dv

kb5ga3dv2#

我在示例中使用PAnsiChar是有原因的。看起来OutputLength是以字节而不是字符来度量的,所以我确保使用了一个总是以字节来度量长度的类型。您还可以注意到,我将OutputString的声明显示为AnsiString
由于编辑控件存储的是Unicode,因此会在AnsiStringUnicodeString之间进行转换。这将考虑系统的当前代码页,但这可能不是您想要的。您可能希望将变量声明为RawByteString。这不会有任何代码页与之关联,因此不会有任何意外的转换。
不要使用字符串来存储二进制数据。如果你正在构建一个相当于十六进制编辑器的东西,那么你就是在使用二进制数据。记住这一点很重要。即使你的二进制数据 * 碰巧 * 主要由可以解释为文本的字节组成,你不能把数据当作文本,否则你会遇到你所看到的问题--字符不像预期的那样出现。如果您从SCSI设备获得一堆字节,则将它们存储在字节数组中,而不是字符数组中。
在十六进制编辑器中,你会注意到它们总是显示字节的十六进制值,它们可能会显示那些被解释为字符的字节,但这是次要的,它们通常只显示可以表示ASCII字符的字节;他们不会试图在基本的显示上做得太花哨。好的十六进制编辑器也会提供显示解释为宽字符的数据。这有助于调试,因为用户可以用多种方式查看相同的数据。但它们只是数据的视图。它们实际上并没有改变数据的二进制内容。

7kqas0il

7kqas0il3#

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

相关问题