Потеря данных при передаче из байтового буфера в AnsiString - PullRequest
0 голосов
/ 08 мая 2018

Я пытаюсь отправить файл AMR размером 4063 байта (только для тестирования) с моего CentOS VPS

nc IP 45500 < sample.amr 

Но когда приложение получает, оно просто показывает вырезанные данные:

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

2617: 

Странная вещь: если я редактирую файл AMR и удаляю отмеченный символ:

enter image description here

И снова отправьте тот же файл AMR, который я получаю:

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

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

.. больше данных, в частности, до следующего NUL-символа

enter image description here

Это код моего сокета 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

1 Ответ

0 голосов
/ 08 мая 2018

Существует две основные причины, по которым ваш код не работает:

  • вы используете версию Delphi для Unicode, поэтому тип string отображается на UnicodeString вместо AnsiString, как вы ожидаете.

  • внутренне, метод TMemo.Lines.Add() передает строку в окно TMemo, используя сообщение EM_REPLACESEL, которое обрабатывает входную строку как завершенную нулем. Вот почему содержимое вашего файла усекается до nul "символов".

Как говорили другие люди в комментариях, вы пытаетесь отобразить двоичные данные, как если бы они были текстовыми, но это не текст. Вместо этого сохраните необработанные двоичные данные как есть в реальном файле на жестком диске. Если вы хотите отобразить байты файла в вашем пользовательском интерфейсе, отобразите их в текстовом безопасном формате, например, в шестнадцатеричном формате.

Попробуйте что-нибудь еще подобное:

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...