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

发布于 2024-07-15 04:19:18 字数 1913 浏览 6 评论 0原文

我得到 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

时光清浅 2024-07-22 04:19:18

一些评论:

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

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

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

Some comments:

  1. Your question is very unclear. What exactly do you want to do?
  2. Your question reads terrible, please check your text with a spelling checker.
  3. The question you are referring to is this one: Delphi accessing data from dynamic array that is populated from an untyped pointer
  4. Please give a complete code sample of your function like you did in your previous question, I want to know if you implemented Rob Kennedy's suggestion or the code you gave yourself in a following answer (let's hope not :) )
  5. As far a I understand your question: You're sending a query to your SCSI device and you get an array of bytes back which you store in the variable OutputData. After that you want to show your data to the user. So your real question is: How to show an array of bytes to the user?
  6. Login as the same user and don't create an account for every new question. That way we can track your question history an can find out what you mean by 'getting advice'.

Some assumptions and suggestions if I'm right about the true meaning of your question:

  1. Showing your data as a hex string won't give any problems
  2. Showing your data in a normal Memo field gives you problems, although a Delphi string can contain any character, including 0 bytes, displaying them will give you problems. A TMemo for example will show your data till the first 0 byte. What you have to do (and you gave the answer yourself), is replacing non viewable characters with a dummy. After that you can show your data in a TMemo. Actually all hex viewers do the same, characters that cannot be printed will be shown as a dot.
九局 2024-07-22 04:19:18

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

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

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

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

I used PAnsiChar in my example for a reason. It looked like OutputLength 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 of OutputString as an AnsiString.

Since the edit control stored Unicode, though, there will be a conversion between AnsiString and UnicodeString. 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 a RawByteString 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.

老娘不死你永远是小三 2024-07-22 04:19:18

当您过滤掉不可见的字符时...您可能需要决定如何处理其中的几个字符,例如 #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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文