#delphi #delphi-7
#delphi #delphi-7
Вопрос:
Я разрабатываю проект с помощью Delphi и хочу преобразовать массив байтов в строковый тип. Как я могу это сделать?
Примеры кодов C #:
private void ListenerOnDataTransmit(DataTransmitEventArgs e)
{
transmittedMsg = BitConverter.ToString(e.TransmittedBytes, 0, e.TransmittedBytes.Length);
try { Invoke(new EventHandler(UpdateTransmittedMessagesListView)); }
catch { }
}
Комментарии:
1. Вы забыли сказать нам, что вы подразумеваете под «преобразованием массива байтов в строку». Существует несколько различных интерпретаций, все разумные: (1) обработайте массив байтов как ASCII и получите кодируемый им текст; (2) обработайте массив байтов как UTF8 и получите кодируемый им текст; (3) получите необработанное шестнадцатеричное представление массива данных; (4) получите необработанныйдвоичное представление массива данных; и т.д. В последних случаях вы хотите сгруппировать цифры?
Ответ №1:
BitConverter.ToString()
Метод «Преобразует числовое значение каждого элемента указанного массива байтов в эквивалентное шестнадцатеричное строковое представление». Вы можете сделать то же самое вручную в Delphi 7, используя SysUtils.IntToHex()
функцию в цикле, например:
uses
..., SysUtils;
var
bytes: array of byte;
s: string;
i: Integer;
begin
bytes := ...;
s := '';
if bytes <> nil then
begin
s := IntToHex(bytes[0], 2);
for i := 1 to High(bytes) do
s := s '-' IntToHex(bytes[i], 2);
end;
end;
Комментарии:
1. Совершенно допустимо, но (очень) неэффективно для длинных буферов из-за постоянного перераспределения строки.
2. @AndreasRejbrand Да, есть много разных способов подойти к этому. Выше приведен только один пример.
3. Верно. И для небольших буферов это, безусловно, достаточно хорошо, так что 1.
4. По крайней мере, теперь у нас есть действительно хороший Q amp; A, который мы можем использовать как канонический для закрытия дубликатов.
5. @RemyLebeau Спасибо, я искал это.
Ответ №2:
Я подозреваю, что вам нужна функция, которая принимает массив байтов (или необработанный указатель на байты) и возвращает строку, содержащую данные в шестнадцатеричной форме.
Для этого я всегда использую следующую свою процедуру:
function BytesToString(ABuf: PByte; ALen: Cardinal): string; overload;
const
HexDigits: array[0..$F] of Char = '0123456789ABCDEF';
var
i: Integer;
begin
if ALen = 0 then
begin
Result := '';
Exit;
end;
SetLength(Result, 3 * ALen - 1);
Result[1] := HexDigits[ABuf^ shr 4];
Result[2] := HexDigits[ABuf^ and $0F];
for i := 1 to ALen - 1 do
begin
Inc(ABuf);
Result[3*i 0] := ' ';
Result[3*i 1] := HexDigits[ABuf^ shr 4];
Result[3*i 2] := HexDigits[ABuf^ and $0F];
end;
end;
type
TByteArray = array of Byte;
function BytesToString(ABytes: TByteArray): string; overload;
begin
Result := BytesToString(PByte(ABytes), Length(ABytes));
end;
Первая перегрузка принимает необработанный указатель и длину, в то время как вторая перегрузка принимает динамический массив байтов.
Это очень быстрая реализация, поскольку я не использую конкатенацию строк (которая требует постоянных перераспределений кучи).
Приведенный выше код был написан специально для старого компилятора Delphi 7 и RTL. Современная версия будет выглядеть примерно так:
function BytesToString(ABuf: PByte; ALen: Cardinal): string; overload;
const
HexDigits: array[0..$F] of Char = '0123456789ABCDEF';
var
i: Integer;
begin
if ALen = 0 then
Exit('');
SetLength(Result, 3 * ALen - 1);
Result[1] := HexDigits[ABuf[0] shr 4];
Result[2] := HexDigits[ABuf[0] and $0F];
for i := 1 to ALen - 1 do
begin
Result[3*i 0] := ' ';
Result[3*i 1] := HexDigits[ABuf[i] shr 4];
Result[3*i 2] := HexDigits[ABuf[i] and $0F];
end;
end;
function BytesToString(ABytes: TArray<Byte>): string; overload;
begin
Result := BytesToString(PByte(ABytes), Length(ABytes));
end;
Приведенный выше код группирует каждый байт с использованием символа пробела. Конечно, вы можете этого не хотеть, но выполнение этого без группировки — более простая задача, поэтому я оставлю это как упражнение.
Комментарии:
1. Честно говоря, я действительно чесал голову, когда увидел
3 * ALen
… То есть, пока я не увидел пробел.2.
PByte
Математика ptr на основе IIRC недоступна в Delphi 7, поэтому я заменил ее еще несколькими методами старой школы.