Delphi 2009 RawByteString причуды - PullRequest
5 голосов
/ 31 января 2009

Предположим, что по какой-то извращенной причине вы хотите отобразить необработанное содержимое байта строки UTF8.

var
  utf8Str : UTF8String;
begin    
  utf8Str := '€ąćęłńóśźż';
end;

(1) Это не так, отображается читаемая форма:

memo1.Lines.Add( RawByteString( utf8Str ));
// output: '€ąćęłńóśźż'

(2) Это, однако, "работает" - обратите внимание на конкатенацию:

memo1.Lines.Add( 'x' + RawByteString( utf8Str ));
// output: 'x€ąćęłńóśźż'

Я понимаю (1), хотя принудительное приведение компилятора к UnicodeString, по-видимому, препятствует отображению переменной RawByteString как есть. Однако почему поведение меняется в (2)?

(3) Еще страннее - давайте изменим конкатенацию:

memo1.Lines.Add( RawByteString( utf8Str ) + 'x' ); 
// output: '€ąćęłńóśźżx'

Я читал о новомодных типах строк в Delphi и думал, что понял, как они работают, но это загадка.

Ответы [ 2 ]

9 голосов
/ 31 января 2009

RawByteString существует только для минимизации количества перегрузок, необходимых для функций, которые работают с различными вариантами AnsiString s с различной привязкой кодовой страницы.

Как правило, не объявляйте переменные типа RawByteString. Не указывайте значения этого типа. Не объединяйте переменные этого типа. Единственное, что вы можете сделать, это:

  • Объявление параметра этого типа (первоначальное намерение)
  • Индексация по такому параметру
  • Поиск по такому параметру
  • Интеллектуальные операции, которые проверяют фактическую кодовую страницу строки, используя функцию StringCodePage.

Например, вы заметите, что сама функция StringCodePage использует RawByteString в качестве типа аргумента. Таким образом, он будет работать с любым AnsiString, вместо того, чтобы выполнять перевод кодовой страницы перед передачей в качестве аргумента.

В вашем случае такие вещи, как конкатенация, в основном не определены. Поведение изменилось между RTM и Update 2, но когда функции конкатенации строк RTL получают несколько строк с разными кодовыми страницами, у них нет простого способа выяснить, какую кодовую страницу следует использовать для последней строки. Это одна из причин, почему вы не должны объединять их, как здесь.

1 голос
/ 02 февраля 2009

Вы не можете добавить строку к TMemo "как есть". Вам всегда нужно какое-то преобразование в Unicode, потому что это все, что TMemo знает в Delphi 2009.

Если вы хотите сделать вид, что ваша UTF8String использует кодовую страницу 1252, сделайте следующее:

var
  utf8Str : UTF8String;
  Raw: RawByteString;
begin
  utf8Str := '€ąćęłńóśźż';
  Raw := utf8Str;
  SetCodePage(Raw, 1252, False);
  Memo.Lines.Add(Raw);
end;

Подробнее см. В моей статье Эффективное использование RawByteString

...