Delphi - 设置字符串和 PAnsiChar 以及其他字符串不显示的问题
我得到 Rob Kennedy 的建议 以及他的建议之一是使用 SetString
,然后将其加载到显示它的 VCL 组件中,这大大提高了我正在开发的应用程序的速度。
我正在使用 Delphi 2009,所以现在 PChar 是 Unicode,
SetString(OutputString, PChar(Output), OutputLength.Value);
edtString.Text := edtString.Text + OutputString;
可以工作,我自己将其更改为 PChar,但由于移动的数据并不总是 Unicode,实际上它通常是 ShortString 数据....所以转到他实际给我的内容use:
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。 我真的很喜欢并且可以使用速度提升,但如果这意味着牺牲读取字符串的能力......那么应用程序的意义何在?
编辑3 - 好吧,现在我已经发现 0-31 是控制字符,32 及以上是有效的,我想我将尝试过滤字符并用 . 这是我稍后计划模仿十六进制编辑器风格的事情。
如果有任何其他建议,我很高兴听到它们,但除此之外,我认为我可以制定一个比原来更快的解决方案,同时满足我的需要。
I was getting advice from Rob Kennedy and one of his suggestions that greatly increased the speed of an app I was working on was to use SetString
and then load it into the VCL component that displayed it.
I'm using Delphi 2009 so now that PChar is Unicode,
SetString(OutputString, PChar(Output), OutputLength.Value);
edtString.Text := edtString.Text + OutputString;
Works and I changed it to PChar myself but since the data being moved isn't always Unicode in fact its usually ShortString Data.... so onto what he actually gave me to use:
SetString(OutputString, PAnsiChar(Output), OutputLength.Value);
edtString.Text := edtString.Text + OutputString;
Nothing shows up but I check in the debugger and the text that normally appeared the way I did it building 1 char at a time in the past was in the variable.
Oddly enough this is not the first time I ran into this tonight. Because I was trying to come up with another way, I took part of his advice and instead of building into a VCL's TCaption I built it into a string variable and then copied it, but when I send it over nothing's displayed. Once again in the debugger the variable that the data is built in... has the data.
for I := 0 to OutputLength.Value - 1 do
begin
OutputString := OutputString + Char(OutputData^[I]);
end;
edtString.Text := OutputString;
The above does not work but the old slow way of doing it worked just fine....
for I := 0 to OutputLength.Value - 1 do
begin
edtString.Text := edtString.Text + Char(OutputData^[I]);
end;
I tried making the variable a ShortString, String and TCaption and nothing is displayed. What I also find interesting is while I build my hex data from the same array into a richedit it's very fast while doing it inside an edit for the text data is very very slow. Which is why I haven't bothered trying to change the code for the richedit as it works superfast as it is.
Edit to add - I think I sorta found the problem but I have no solution. If I edit the value in the debugger to remove anything that can't be displayed (which by the old method used to just not display... not fail) then what I have left is displayed. So if it's just a matter of getting rid of bytes that were turned to characters that are garbage how can I fix that?
I basically have incoming raw data from a SCSI device that's being displayed hex-editor style. My original slow style of adding one char at a time successfully displayed strings and Unicode strings that did not have Unicode-specific characters in them. The faster methods even if working won't display ShortStrings one way and the other way wont display UnicodeStrings that aren't using non 0-255 characters. I really like and could use the speed boost but if it means sacrificing the ability to read the string... then what's the point in the app?
EDIT3 - Alright now that I've figured out that 0-31 is control char and 32 and up is valid I think I'm gonna make an attempt to filter char and replace those not valid with a . which is something I was planning on doing later to emulate hex editor style.
If there are any other suggestions I'd be glad to hear about them but otherwise I think I can craft a solution that's faster than the original and does what I need it to at the same time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
一些评论:
如果我对你的问题的真正含义是正确的,一些假设和建议:
Some comments:
Some assumptions and suggestions if I'm right about the true meaning of your question:
我在示例中使用
PAnsiChar
是有原因的。 看起来OutputLength
是以字节为单位而不是字符来测量的,因此我确保使用长度始终以字节为单位测量的类型。 您还会注意到,我将OutputString
声明显示为AnsiString
。不过,由于编辑控件存储的是 Unicode,因此
AnsiString
和UnicodeString
之间将会进行转换。 这将考虑系统当前的代码页,但这可能不是您想要的。 您可能希望将变量声明为RawByteString
。 这不会有任何与之关联的代码页,因此不会出现任何意外的转换。不要使用字符串来存储二进制数据。 如果您正在构建相当于十六进制编辑器的东西,那么您正在使用二进制数据。 记住这一点很重要。 即使您的二进制数据碰巧主要由可解释为文本的字节组成,您也不能将数据视为文本,否则您将遇到您所看到的问题 - 字符没有按预期出现。 如果您从 SCSI 设备获取一堆字节,请将它们存储在字节数组中,而不是字符数组中。
在十六进制编辑器中,您会注意到它们始终显示字节的十六进制值。 它们可能会显示那些被解释为字符的字节,但这是次要的,它们通常只显示可以表示 ASCII 字符的字节; 他们不会试图对基本的显示过于花哨。 好的十六进制编辑器也将提供显示解释为宽字符的数据。 这有助于调试,因为用户可以通过多种方式查看相同的数据。 但它们只是数据的视图。 他们实际上并没有改变数据的二进制内容。
I used
PAnsiChar
in my example for a reason. It looked likeOutputLength
was being measured in bytes, not characters, so I made sure to use a type whose length is always measured in bytes. You'll also notice that I showed the declaration ofOutputString
as anAnsiString
.Since the edit control stored Unicode, though, there will be a conversion between
AnsiString
andUnicodeString
. That will take the system's current code page into account, but that's probably not what you want. You might want to declare the variable as aRawByteString
instead. That won't have any code page associated with it, so there won't be any unexpected conversions.Don't use strings for storing binary data. If you're building what amounts to a hex editor, then you're working with binary data. It's important to remember that. Even if your binary data happens to consist mostly of bytes that can be interpreted as text, you can't treat the data as text or you'll run into exactly the problems you're seeing — characters that don't appear as expected. If you get a bunch of bytes from your SCSI device, then store them in an array of bytes, not characters.
In hex editors, you'll notice that they always show the hexadecimal values of the bytes. They might show those bytes interpreted as characters, but that's secondary, and they generally only show the bytes that can represent ASCII characters; they don't try to get too fancy with the basic display. The good hex editors will offer to display the data interpreted as wide characters, too. This aids in debugging because the user can look at the same data in multiple ways. But they're just views of the data. They're not actually changing the binary contents of the data.
当您过滤掉不可见的字符时...您可能需要决定如何处理其中的几个字符,例如 #9(Tab)、#10(LF)、#11(Verticle Tab)、#12(FF-或新页),#13(CR)
When you filter out non viewable characters...You'll probably need to decide what to do with a couple of them like #9(Tab), #10(LF), #11(Verticle Tab), #12(FF-or New Page),#13(CR)