从Delphi

时间:2015-12-06 23:22:44

标签: delphi

我正在寻找一种简单的方法,从TStringList(始终" Windows-1252"文本文件)中取出十六进制数据行并将它们切割成记录块(每行可以是不同的长度) )。

在Delphi 7中我用过:

procedure DecodeLineAddr(const aLine: AnsiString; var ByteCount: integer; var Address:Cardinal; var RecType: Integer);
begin
//123 4567 89 0
//:10 4640 00 0000 0600 0200 fa00 004f 7800 1e00 fb00 88
 ByteCount:= StrToInt('$' + copy(aLine, 2, 2));
 Address  := StrToInt('$' + copy(aLine, 4, 4));
 RecType  := StrToInt('$' + copy(aLine, 8, 2));
end;

也就是说,只需从最初的"块信息"中的正确位置复制字符。在该行中,然后添加' $'所以StrToInt会将字符串解释为十六进制。

我逐行处理 - 所以很容易做到这样的事情:

aLineAsTBytes:= TEncoding.ASCII.GetBytes(aStringLst[ndx]);

然后将aLineAsTBytes传递给DecodeLineAddr作为TBytes而不是AnsiString。

我不清楚我应该如何解码各种字节(或如何正确地刻录它们),以便使用可在桌面和移动设备上运行的代码返回正确的结果。

也就是说,如果使用aLine:TBytes(而不是AnsiString),那相当于:

ByteCount:= StrToInt('$' + copy(aLine, 2, 2));

(是否有更好/更快的处理方式?)

TIA。

EDB

1 个答案:

答案 0 :(得分:1)

您已经做的事情会有效,但您需要做一些调整。最重要的是,将你的功能变成一个"字符串"键入而不是" AnsiString"类型,这意味着您必须转换它。

移动字符串从0开始,因此在移动设备上,您需要从索引中减去1。或者您可以使用我的ocopy()或zcopy()函数,它们在所有平台上都执行相同的操作。如果您正在处理旧的Windows代码,请使用ocopy(),它会将基于0的字符串视为基于1的字符串,从而更容易移植。

const
{$IFNDEF MSWINDOWS}
  STRZ = 1;
{$ELSE}
  STRZ = 0;
function zcopy(sString: string; iStartZeroBased: nativeint; iLength: nativeint):    string;
begin
  result := '';
  setlength(result, lesserof(iLength, length(sString)-iStartZerobased));
  movemem32(@result[strz], @sString[(strz+iStartZeroBased)],    length(result)*sizeof(char));
end;

function ocopy(sString: string; iStartOneBased: nativeint; iLength:     nativeint): string;
begin
  result := zcopy(sString, iStartOneBased-1, iLength);
end;

接下来,请使用此代码,这不是一个完全完整的解决方案,但会在移动设备上为您提供大部分的ansi-string支持(对指针有一些细微的警告)。但基本上你可以通过简单地将ansistring分配给字符串类型或反之亦然来转换字符串。我不得不从一些依赖项中解决这个问题,所以我不能保证它会立即编译,但它应该非常接近。

unit iosbytestring;

interface

uses
  sysutils, classes;

{$IFNDEF MSWINDOWS}
const STRZERO = 0;
{$ELSE}
const STRZERO = 1;
{$ENDIF}

type
  Tiosansichar = packed record
  private
    b: byte;
    class function AnsiFromChar(c: char): byte;static;
    class function CharFromAnsi(b: byte): char;static;

  public
    function ToChar: char;
    function ToOrd: byte;
    class operator Implicit(const s: Tiosansichar): string;
    class operator Implicit(const s: Tiosansichar): char;
    class operator Implicit(const s: Tiosansichar): byte;
    class operator Implicit(const s: Tiosansichar): pointer;
  end;

  Tiosbytestring = record
  private
    Fbytes: TBytes;
    function GetChar(idx: nativeint): char;
    procedure SetChar(idx: nativeint; const Value: char);
    function GetAddrOf(idx: nativeint): pbyte;
    function getbyte(idx: nativeint): byte;
    procedure setbyte(idx: nativeint; const Value: byte);
  public
    property chars[idx: nativeint]: char read GetChar write SetChar;
    property bytes[idx: nativeint]: byte read getbyte write setbyte;
    property addrof[idx: nativeint]: pbyte read GetAddrOf;
    class operator Implicit(const s: TIOSByteString): string;
    class operator Implicit(const s: string): TIOSByteString;
    class operator Add(const s1,s2: TIOSByteString): TIOSByteSTring;
    class operator Add(const s1: string; const s2: TIOSByteString):     TIOSByteSTring;
    class operator Add(const s1: TIOSByteString; const s2: string): TIOSByteSTring;
    procedure FromString(s: string);
    function ToString: string;
    procedure SetLength(i: nativeint);
  end;
  TIOSAnsiString = TIOSByteString;
{$IFNDEF MSWINDOWS}
  ansistring = TIOSByteString;
  utf8string = TIOSByteString;
  widestring = string;
{$ENDIF}


implementation

{ iosbytestring }

class operator Tiosbytestring.Add(const s1: string;
const s2: TIOSByteString): TIOSByteSTring;
var
  ss2,ss3: string;
begin
  ss2 := s2.ToString;
  ss3 := s1+ss2;
  result.FromString(ss3);

end;

class operator Tiosbytestring.Add(const s1: TIOSByteString;
const  s2: string): TIOSByteSTring;
var
  ss1,ss3: string;
begin
  ss1 := s1.ToString;
  ss3 := ss1+s2;
  result.FromString(ss3);
end;




procedure Tiosbytestring.FromString(s: string);
begin
  Fbytes := TEncoding.ANSI.GetBytes(s);

end;

function Tiosbytestring.GetAddrOf(idx: nativeint): pbyte;
begin
  result := @Fbytes[idx];
end;

function Tiosbytestring.getbyte(idx: nativeint): byte;
begin
  result := Fbytes[idx-strzero];
end;

function Tiosbytestring.GetChar(idx: nativeint): char;
begin
  result := Tiosansichar.CharFromAnsi(Fbytes[idx-strzero]);
end;

class operator Tiosbytestring.Implicit(const s: TIOSByteString): string;
begin
  result := s.ToString;

end;

class operator Tiosbytestring.Implicit(const s: string): TIOSByteString;
begin
  result.FromString(s);
end;

procedure Tiosbytestring.setbyte(idx: nativeint; const Value: byte);
begin
  Fbytes[idx-strzero] := value;
end;

class operator Tiosbytestring.Add(const s1,
  s2: TIOSByteString): TIOSByteSTring;
var
  ss1,ss2,ss3: string;
begin
  ss1 := s1.ToString;
  ss2 := s2.ToString;
  ss3 := ss1+ss2;
  result.FromString(ss3);

end;

procedure Tiosbytestring.SetChar(idx: nativeint; const Value: char);
begin
  Fbytes[idx-strzero] := Tiosansichar.AnsiFromChar(value);
end;

procedure Tiosbytestring.SetLength(i: nativeint);
begin
  system.setlength(Fbytes,i);
end;

function Tiosbytestring.ToString: string;
begin
  result := TEncoding.ANSI.GetString(Fbytes);
end;

{ Tiosansichar }


class function Tiosansichar.AnsiFromChar(c: char): byte;
var
  s: string;
  te: TEncoding;
  b: TBytes;
begin
  s := c;

  b := TEncoding.ANSI.GetBytes(c);
  result := b[0];


end;


class function Tiosansichar.CharFromAnsi(b: byte): char;
var
  s: string;
  bytes: TBytes;
begin
  system.setlength(bytes, 1);
  bytes[0] := b;
  s := TEncoding.ANSI.GetString(bytes, 0, 1);
  result := s[low(s)];
end;

class operator Tiosansichar.Implicit(const s: Tiosansichar): char;
begin
  result := s.ToChar;
end;

class operator Tiosansichar.Implicit(const s: Tiosansichar): string;
begin
  result := s.ToChar;
end;

class operator Tiosansichar.Implicit(const s: Tiosansichar): pointer;
begin
  result := @s.b;
end;

class operator Tiosansichar.Implicit(const s: Tiosansichar): byte;
begin
  result := s.b;
end;

function Tiosansichar.ToChar: char;
begin
  result := CharFromAnsi(b);
end;

function Tiosansichar.ToOrd: byte;
begin
  result := b;
end;

end.

所以只需添加上面的单元,将其添加到您的uses子句中,神奇地说,您的移动平台上会有一个ansistring类型。继续在Windows上使用标准的ansistring类型。

如果一切顺利......这就是你的代码片段可能最终结束的方式。

procedure DecodeLineAddr(const aLine: AnsiString; var ByteCount: integer; var     Address:Cardinal; var RecType: Integer);
var
  aLineWide: string;
begin
  aLineWide = aLine;
  //123 4567 89 0
  //:10 4640 00 0000 0600 0200 fa00 004f 7800 1e00 fb00 88
  ByteCount:= StrToInt('$' + ocopy(aLineWide, 2, 2));
  Address  := StrToInt('$' + ocopy(aLineWide, 4, 4));
  RecType  := StrToInt('$' + ocopy(aLineWide, 8, 2));
end;