我已将我的项目从XE5迁移到10西雅图。我仍在使用ANSII代码与设备通信。在我的新版本中,Seattle IDE在Char数组中发送†字符而不是空格字符(在Ansii代码中为#32)。我需要将空格字符数据发送到文本文件,但我不能。
我尝试了#32(就像我之前使用的那样),#032和#127但是它没有用。有什么想法吗?
以下是我的使用方法:
fillChar(X,50,#32);
方法签名(var X; count:Integer; Value:Ordinal)
答案 0 :(得分:4)
如果要使用ANSI与设备进行通信,则应将数组定义为
x: array[1..50] of AnsiChar;
在这种情况下,请使用<{1}}字符填充
space
使用AnsiChar数组作为通信缓冲区可能会在Unicode环境中变得麻烦,因此我建议使用FillChar(x, 50, #32);
数组作为通信缓冲区
byte
并使用
初始化它x: array[1..50] of byte;
答案 1 :(得分:4)
尽管有名称,FillChar()
填充字节,而不是字符。
Char
是Delphi 2009+中WideChar
(2个字节)的别名,在以前的版本中,它是AnsiChar
(1个字节)的别名。
因此,如果您有一个50个元素的WideChar
元素数组,则该数组的大小为100个字节。当您致电fillChar(X,50,#32)
时,它会填充前50个字节,每个字段的值为$20
。因此,前25个WideChar
元素的值为$2020
(又称Unicode代码点U+2020 DAGGER
,†
),而后25个元素的值不会有任何有意义的值。
使用指定值填充连续字节。
在Delphi中, FillChar使用Value指定的值填充Count连续字节(由X引用)(Value可以是Byte或AnsiChar类型)
请注意,如果X是UnicodeString,则可能无法按预期工作,因为 FillChar需要字节数,这与字符数不同。
此外,填充字符是单字节字符。因此,当Buf是UnicodeString时,代码为FillChar(Buf,Length(Buf),#9);使用代码点$ 0909填充Buf,而不是$ 09 。在这种情况下,您应该使用StringOfChar例程。
Embarcadero的Unicode Migration Resources白皮书也解释了这一点,例如Cary Jensen撰写的Delphi Unicode Migration for Mere Mortals: Stories and Advice from the Front Lines第28页:
实际上,这类代码的复杂性本身与指针和缓冲区无关。问题是由于Chars被用作指针。因此,现在以字节为单位的字符串和字符的大小发生了变化,这些代码所包含的基本假设之一不再有效:单个字符的长度为一个字节。
由于这种类型的代码对于Unicode转换(以及一般的维护)来说是如此有问题,并且需要详细检查,因此可以在可能的情况下重构这个代码。简而言之,从这些操作中删除Char类型,并切换到另一种更合适的数据类型。例如,Olaf Monien写道,&#34;我不建议在Char(或String)类型上使用面向字节的操作。如果你需要一个字节缓冲区,那么使用'Byte'作为[数据]类型:缓冲区:字节[0..255]的字节;。&#34;
例如,过去你可能会做过这样的事情:
var Buffer: array[0..255] of AnsiChar; begin FillChar(Buffer, Length(Buffer), 0);
如果您只想转换为Unicode,则可能会进行以下更改:
var Buffer: array[0..255] of Char; begin FillChar(Buffer, Length(buffer) * SizeOf(Char), 0);
另一方面,可以提出一个很好的论据,可以将Char数组的使用作为缓冲区,并切换到Byte数组,正如Olaf建议的那样。这看起来像这样(由于缓冲区的大小,它与第一段相似,但与第二段不同):
var Buffer: array[0..255] of Byte; begin FillChar(Buffer, Length(buffer), 0);
更好的是,使用FillChar的第二个参数,无论数组的数据类型如何,它都有效:
var Buffer: array[0..255] of Byte; begin FillChar(Buffer, Length(buffer) * SizeOf(Buffer[0]), 0);
最后两个例子的优点是你首先拥有了你真正想要的东西,一个可以保存字节大小值的缓冲区。 (并且Delphi不会尝试应用任何形式的隐式字符串转换,因为它使用字节而不是代码单元。)而且,如果你想做指针数学,你可以使用PByte。 PByte是指向字节的指针。
当您与需要指向字符或字符数组的指针的外部库进行交互时,可能无法进行更改的地方。在这些情况下,他们确实要求缓冲字符,这些通常是AnsiChar类型。
因此,要解决您的问题,由于您要与需要Ansi数据的外部设备进行交互,因此您需要将数组声明为使用AnsiChar
或Byte
元素而不是(Wide)Char
元素。然后,您原来的FillChar()
电话会再次正常运行。