从字节缓冲区传输到 AnsiString 时丢失数据

Losing data when transfering from Bytes Buffer to AnsiString

我正在尝试从我的 CentOS 发送一个 4063 字节的 AMR 文件(仅用于测试)VPS

nc IP 45500 < sample.amr 

但是当应用程序收到它时,它只显示一个剪切数据:

1448: #!AMR-WB
Ô_Æ ÅѤm^8E•Ì^^ìÖõ¾_€°

2617: 

奇怪的是:如果我编辑 AMR 文件并删除标记的字符:

然后再次发送我收到的相同 AMR 文件:

1448: #!AMR-WB
Ô_Æ ÅѤm^8E•Ì^^ìÖõ¾_€°ÀžH¯ë2Çc oÚÖɾøy$Ý

2616: ¢Khw^è“ʺ\?¬šJ£<é<'

.. 更多数据,特别是下一个 NUL 字符

这是我的 Socket 的代码 onClientRead

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  received,a: string;
  size,i: Integer;
  AnsiStr: String;
  Bytes: array[0..2048*256] of Byte;
begin

  Size := Socket.ReceiveLength;
  Socket.ReceiveBuf(Bytes[0], Size);

  SetString(AnsiStr, PAnsiChar(@Bytes[0]), Size);
  received := IntToStr(Size)+': '+AnsiStr;

  Memo1.Lines.Add(received);
  Memo1.Lines.Add(' ');
end;

我相信 SetString 命令导致了这个,但不确定如何接收整个数据。我只想接收整个文件并将其复制到我这边的新 AMR 文件中。

额外: 我试图从我的服务器发送到我的电脑的文件位于: http://techslides.com/demos/samples/sample.amr

您的代码不起作用的主要原因有两个:

  • 您使用的是 Delphi 的 Unicode 版本,因此 string 类型映射到 UnicodeString,而不是您期望的 AnsiString .

  • 在内部,TMemo.Lines.Add() 方法使用 EM_REPLACESEL 消息将字符串传递给 TMemo window,它将输入字符串视为 null -终止。这就是为什么您的文件内容在 nul "characters".

  • 处被截断的原因

正如其他人在评论中所说,您试图将二进制数据显示为文本,但它不是文本。将原始二进制数据按原样保存到硬盘上的实际文件中。如果您想在 UI 中显示文件字节,请以文本安全格式显示它们,例如十六进制。

试试像这样的东西:

procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  Socket.Data := TFileStream.Create('<some path>\sample.amr', fmCreate);
end;

procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject;
  Socket: TCustomWinSocket);
begin
  TFileStream(Socket.Data).Free;
end;

procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
var
  Size: Integer;
  Bytes: TBytes;
  Received: string;
begin
  Size := Socket.ReceiveLength;
  if Size < 1 then Exit;

  SetLength(Bytes, Size);
  Size := Socket.ReceiveBuf(Bytes[0], Size);
  if Size < 1 then Exit;

  TFileStream(Socket.Data).WriteBuffer(Bytes[0], Size);

  SetLength(Received, Size*2);
  BinToHex(Bytes[0], PChar(Received), Size);

  Memo1.Lines.Add(IntToStr(Size) + ': ' + Received);
  Memo1.Lines.Add(' ');
end;