在Char数组中发送†字符而不是空格字符

时间:2016-05-03 15:08:23

标签: arrays delphi char pascal delphi-10-seattle

我已将我的项目从XE5迁移到10西雅图。我仍在使用ANSII代码与设备通信。在我的新版本中,Seattle IDE在Char数组中发送†字符而不是空格字符(在Ansii代码中为#32)。我需要将空格字符数据发送到文本文件,但我不能。

我尝试了#32(就像我之前使用的那样),#032和#127但是它没有用。有什么想法吗?

以下是我的使用方法:

fillChar(X,50,#32);

方法签名(var X; count:Integer; Value:Ordinal)

2 个答案:

答案 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个元素的值不会有任何有意义的值。

FillChar() documentation

中解释了此问题
  

使用指定值填充连续字节

     

在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数据的外部设备进行交互,因此您需要将数组声明为使用AnsiCharByte元素而不是(Wide)Char元素。然后,您原来的FillChar()电话会再次正常运行。