TIdTCPClient读取字节

时间:2015-04-30 12:44:32

标签: delphi

Seg参数:

  liBinID       : LongInt;
  liAux         : LongInt;
  classID       : TJPIPDatabinClass;
  liCodestreamID: LongInt;
  iOffset       : Integer;
  iLength       : Integer;
  arrData       : TBytes;
  isFinal       : Boolean;
  isEOR         : Boolean;
  isComplete    : Boolean;

错误功能:

function TJPIPDataInputStream.readSegment: TJPIPDataSegment;
var
  m   : Integer;
  id  : LongInt;
  seg : TJPIPDataSegment;
  B   : Byte;
begin
  id:= readVBAS;
  if id < 0 then
  begin
    Result:= nil;
    Exit;
  end;
  seg:= TJPIPDataSegment.Create;
  seg.liBinID:= id;

  if vbasFstByte = 0 then
  begin
    seg.isEOR:= true;
    seg.liBinID:= formMain.client.IOHandler.ReadByte;
    if seg.liBinID < 0 then
      ShowMessage('EOF reached before completing EOR message');
    seg.iLength:= Integer(readVBAS);
  end
  else
  begin
    seg.isEOR:= false;
    seg.liBinID:= seg.liBinID and (not LongInt($70 shl ((vbasLength - 1) * 7)));
    seg.isFinal:= ((vbasFstByte and $10) <> 0);
    m:= (vbasFstByte and $7F) shr 5;
    if m = 0 then
      ShowMessage('Invalid Bin-ID value format')
    else if m >= 2 then
    begin
      classId:= readVBAS;
      if m > 2 then
        codestream:= readVBAS;
    end;
    seg.liCodestreamID:= codestream;


    if classId = jpipdatabinclass.FPRECINCT_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FPRECINCT_DATABIN
    else if classId = jpipdatabinclass.FTILE_HEADER_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FTILE_HEADER_DATABIN
    else if classId = jpipdatabinclass.FTILE_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FTILE_DATABIN
    else if classId = jpipdatabinclass.FMAIN_HEADER_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FMAIN_HEADER_DATABIN
    else if classId = jpipdatabinclass.FMETA_DATABIN.getStandardClassID then
      seg.classID:= jpipdatabinclass.FMETA_DATABIN;


    if seg.classID = nil then
      ShowMessage('Invalid databin classID');

    seg.iOffset:= Integer(readVBAS);
    seg.iLength:= Integer(readVBAS);

    if (classId = EXTENDED_PRECINCT_DATA_BIN_CLASS) or (classId = EXTENDED_TILE_DATA_BIN_CLASS) then
      seg.liAux:= readVBAS;
  end;

  if seg.iLength > 0 then
  begin
    if seg.arrData = nil then
      SetLength(seg.arrData, seg.iLength);

    if Length(seg.arrData) < seg.iLength then
      SetLength(seg.arrData, seg.iLength);

    formMain.client.IOHandler.ReadBytes(TIdBytes(seg.arrData), Length(seg.arrData));
//    if inStream.read(seg.data, 0, seg.alength) <> seg.alength then
//      ShowMessage('EOF reached before read' + IntToStr(seg.alength) + ' bytes');
  end;
  Result:= seg;
end;

arrData是TBytes;

iLength是整数;

iLength = 12;

arrData长度也是12。

我调试了它,输出长度为24.前12个元素为0,其他12个元素为真值。但是我无法理解,我将arrData的长度设置为12但是在读取之后,它返回arrData的长度为24。

编辑它总是给出我给出的x2长度。

1 个答案:

答案 0 :(得分:2)

TIdIOHandler.ReadBytes()默认包含AAppend个可选参数{/ 1}}:

True

这意味着任何读取的字节都将附加到现有数组的末尾。由于您正在预先分配数组,因此它最终会变成两倍大小。

您需要:

  1. 删除预分配,让procedure ReadBytes(var VBuffer: TIdBytes; AByteCount: Integer; AAppend: Boolean = True); 为您分配数组:

    ReadBytes()
  2. 保留预分配并将seg.arrData := nil; if seg.iLength > 0 then begin formMain.client.IOHandler.ReadBytes(TIdBytes(seg.arrData), seg.iLength); end; 设置为False,以便AAppend填充现有内存而不是附加到其中:

    ReadBytes()