Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Как избежать потери байтов при конкатенации строковых литералов в Delphi и Pascal?

Delphi , Синтаксис , Текст и Строки

 

Введение

В процессе работы с Delphi и Pascal разработчики иногда сталкиваются с проблемой потери данных при конкатенации строковых литералов, содержащих бинарные данные. Эта статья исследует причины такого поведения и предлагает правильные подходы к работе с бинарными данными в Object Pascal.

Проблема: неожиданная потеря байтов

Рассмотрим пример из обсуждения, где происходит потеря байтов:

// Компиляция с кодовой страницей 936
program Problem;

const
  strPublicKey: RawByteString =
    #$30#$3C#$30#$0D#$06#$09#$2A#$86#$48#$86#$F7#$0D#$01#$01#$01#$05 +
    #$00#$03#$2B#$00#$30#$28#$02#$21#$00#$A4#$65#$B8#$CD#$B4#$29#$A9 +
    #$64#$1A#$C5#$80#$55#$22#$1B#$BB#$C5#$98#$36#$B9#$23#$0C#$CA#$D4 +
    #$A8#$B8#$7C#$E6#$32#$E3#$89#$3D#$77#$02#$03#$01#$00#$01;
begin
  Writeln(Length(strPublicKey)); // ожидается 62, получаем 58 - почему?
  Readln;
end.

В этом примере при конкатенации строковых литералов происходит потеря 4 байтов из 62.

Причины проблемы

Основная причина потери данных кроется в неявном преобразовании строк между разными кодировками:

  1. Первый строковый литерал интерпретируется как UnicodeString без потери данных
  2. Последующие строковые литералы содержат недопустимые последовательности байтов в CP936
  3. При операции UnicodeString + AnsiString компилятор преобразует AnsiString в UnicodeString
  4. Неправильные последовательности байтов заменяются символом '?'

Это поведение связано с тем, что строки в Delphi предназначены прежде всего для текстовых данных, а не для произвольных бинарных данных.

Правильное решение: использование массивов байтов

Для работы с бинарными данными следует использовать массивы байтов вместо строк:

const
  PublicKey: array[0..61] of Byte = (
    $30, $3C, $30, $0D, $06, $09, $2A, $86, $48, $86, $F7, $0D, $01, $01, $01, $05,
    $00, $03, $2B, $00, $30, $28, $02, $21, $00, $A4, $65, $B8, $CD, $B4, $29, $A9,
    $64, $1A, $C5, $80, $55, $22, $1B, $BB, $C5, $98, $36, $B9, $23, $0C, $CA, $D4,
    $A8, $B8, $7C, $E6, $32, $E3, $89, $3D, $77, $02, $03, $01, $00, $01
  );
begin
  Writeln(Length(PublicKey)); // корректно выведет 62
  Readln;
end.

Альтернативные подходы

  1. Использование RawByteString с явным указанием кодовой страницы:
    const strPublicKey: RawByteString =
    #$30#$3C#$30#$0D#$06#$09#$2A#$86#$48#$86#$F7#$0D#$01#$01#$01#$05 +
    #$00#$03#$2B#$00#$30#$28#$02#$21#$00#$A4#$65#$B8#$CD#$B4#$29#$A9 +
    #$64#$1A#$C5#$80#$55#$22#$1B#$BB#$C5#$98#$36#$B9#$23#$0C#$CA#$D4 +
    #$A8#$B8#$7C#$E6#$32#$E3#$89#$3D#$77#$02#$03#$01#$00#$01;

    var Bytes: TBytes;
    begin
    SetCodePage(RawByteString(strPublicKey), CP_ACP, False);
    SetLength(Bytes, Length(strPublicKey));
    Move(PAnsiChar(strPublicKey)^, Bytes[0], Length(strPublicKey));
    end;

  2. Использование TBytes и конвертации:
    var Bytes: TBytes;
    begin
     Bytes := TEncoding.ASCII.GetBytes('текст для преобразования');
    end;

Когда допустимо использовать строки для бинарных данных?

Хотя в большинстве случаев следует использовать массивы байтов, есть ситуации, где строки допустимы:

  1. Работа с устройствами через COM-порт, использующими простой текстовый протокол
  2. Легаси-код, который сложно переписать
  3. Данные, гарантированно содержащие только допустимые символы

Выводы

  1. Используйте правильные типы данных: байты для бинарных данных, строки - для текста
  2. Массивы байтов - наиболее надежное решение для работы с бинарными данными
  3. Избегайте неявных преобразований между разными кодировками
  4. Будьте осторожны с конкатенацией строк, содержащих бинарные данные

Следование этим принципам поможет избежать трудноуловимых ошибок и сделает ваш код более надежным и переносимым.

Создано по материалам из источника по ссылке.

Статья описывает проблему потери байтов при конкатенации строковых литералов в Delphi и Pascal, объясняет её причины и предлагает решения, включая использование массивов байтов и альтернативные подходы для работы с бинарными данными.


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Текст и Строки ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-06-18 02:58:10/0.0059709548950195/0