Поиск…


Строковые типы

Delphi имеет следующие типы строк (в порядке их популярности):

Тип Максимальная длина Минимальный размер Описание
string 2 Гб 16 байт Управляемая строка. Псевдоним для AnsiString через Delphi 2007 и псевдоним для UnicodeString с Delphi 2009.
UnicodeString 2 Гб 16 байт Управляемая строка в формате UTF-16.
AnsiString 2 Гб 16 байт Управляемая строка в формате ANSI в формате Unicode. Начиная с Delphi 2009, он содержит явный индикатор кодовой страницы.
UTF8String 2 Гб 16 байт Управляемая строка в формате UTF-8, реализованная как AnsiString с кодовой страницей UTF-8.
ShortString 255 символов 2 байта Унаследованная, фиксированная длина, неуправляемая строка с очень небольшими накладными расходами
WideString 2 Гб 4 байта Предназначен для COM-взаимодействия, управляемой строки в формате UTF-16. Эквивалентен типу Windows BSTR .

UnicodeString и AnsiString - подсчет ссылок и копирование на запись (COW).
ShortString и WideString не подсчитываются и не имеют семантики COW.

Струны

uses
  System.Character;

var
  S1, S2: string;
begin
  S1 := 'Foo';
  S2 := ToLower(S1); // Convert the string to lower-case
  S1 := ToUpper(S2); // Convert the string to upper-case

Символов

2009
uses
  Character;

var
  C1, C2: Char;
begin
  C1 := 'F';
  C2 := ToLower(C1); // Convert the char to lower-case
  C1 := ToUpper(C2); // Convert the char to upper-case

Предложение uses должно быть System.Character если версия XE2 или выше.

Верхний и нижний регистры

uses
  SysUtils;

var
  S1, S2: string;
begin
  S1 := 'Foo';
  S2 := LowerCase(S1); // S2 := 'foo';
  S1 := UpperCase(S2); // S1 := 'FOO';

присваивание

Присвоение строки различным типам строк и поведение среды выполнения в отношении них. Распределение памяти, подсчет ссылок, индексированный доступ к символам и ошибки компилятора, описанные кратко, где это применимо.

var
  SS5: string[5]; {a shortstring of 5 chars + 1 length byte, no trailing `0`}
  WS: Widestring; {managed pointer, with a bit of compiler support}
  AS: ansistring; {ansistring with the default codepage of the system}
  US: unicodestring; {default string type}
  U8: UTF8string;//same as AnsiString(65001)
  A1251: ansistring(1251); {ansistring with codepage 1251: Cryllic set}
  RB: RawbyteString; {ansistring with codepage 0: no conversion set}
begin
  SS5:= 'test'; {S[0] = Length(SS254) = 4, S[1] = 't'...S[5] = undefined}
  SS5:= 'test1'; {S[0] = 5, S[5] = '1', S[6] is out of bounds}
  SS5:= 'test12'; {compile time error}
  WS:= 'test'; {WS now points to a constant unicodestring hard compiled into the data segment}
  US:= 'test'+IntToStr(1); {New unicode string is created with reference count = 1}
  WS:= US; {SysAllocateStr with datacopied to dest, US refcount = 1 !}
  AS:= US; {the UTF16 in US is converted to "extended" ascii taking into account the codepage in AS possibly losing data in the process}  
  U8:= US; {safe copy of US to U8, all data is converted from UTF16 into UTF8}
  RB:= US; {RB = 'test1'#0 i.e. conversion into RawByteString uses system default codepage}
  A1251:= RB; {no conversion takes place, only reference copied. Ref count incremented }

Подсчет ссылок

Подсчет ссылок на строки является потокобезопасным. Для защиты процесса используются блокировки и обработчики исключений. Рассмотрим следующий код с комментариями, указывающими, где компилятор вводит код во время компиляции для управления подсчетами ссылок:

procedure PassWithNoModifier(S: string);
// prologue: Increase reference count of S (if non-negative),
//           and enter a try-finally block
begin
  // Create a new string to hold the contents of S and 'X'. Assign the new string to S,
  // thereby reducing the reference count of the string S originally pointed to and
  // brining the reference count of the new string to 1.
  // The string that S originally referred to is not modified.
  S := S + 'X';
end;
// epilogue: Enter the `finally` section and decrease the reference count of S, which is
//           now the new string. That count will be zero, so the new string will be freed.
    
procedure PassWithConst(const S: string);
var
  TempStr: string;
// prologue: Clear TempStr and enter a try-finally block. No modification of the reference
//           count of string referred to by S.
begin
  // Compile-time error: S is const.
  S := S + 'X';
  // Create a new string to hold the contents of S and 'X'. TempStr gets a reference count
  // of 1, and reference count of S remains unchanged.
  TempStr := S + 'X';
end;
// epilogue: Enter the `finally` section and decrease the reference count of TempStr,
//           freeing TempStr because its reference count will be zero.

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

Кодировки

Строковые типы, такие как UnicodeString, AnsiString, WideString и UTF8String, хранятся в памяти с использованием их соответствующей кодировки (подробнее см. «Типы строк»). Присвоение одного типа строк в другой может привести к конверсии. Строка типа предназначена для независимого кодирования - вы никогда не должны использовать ее внутреннее представление.

Класс Sysutils.TEncoding предоставляет метод GetBytes для преобразования string в TBytes (массив байтов) и GetString для преобразования TBytes в string . Класс Sysutils.TEncoding также предоставляет множество предопределенных кодировок в качестве свойств класса.

Один из способов решения кодировок - использовать только тип string в вашем приложении и использовать TEncoding каждый раз, когда вам нужно использовать определенную кодировку - как правило, в операциях ввода-вывода, вызовах DLL и т. Д. ...

procedure EncodingExample;
var hello,response:string;
    dataout,datain:TBytes;
    expectedLength:integer;
    stringStream:TStringStream;
    stringList:TStringList;
     
begin
  hello := 'Hello World!Привет мир!';
  dataout := SysUtils.TEncoding.UTF8.GetBytes(hello); //Conversion to UTF8
  datain := SomeIOFunction(dataout); //This function expects input as TBytes in UTF8 and returns output as UTF8 encoded TBytes.
  response := SysUtils.TEncoding.UTF8.GetString(datain); //Convertsion from UTF8

  //In case you need to send text via pointer and length using specific encoding (used mostly for DLL calls)
  dataout := SysUtils.TEncoding.GetEncoding('ISO-8859-2').GetBytes(hello); //Conversion to ISO 8859-2
  DLLCall(addr(dataout[0]),length(dataout));
  //The same is for cases when you get text via pointer and length
  expectedLength := DLLCallToGetDataLength();
  setLength(datain,expectedLength);
  DLLCall(addr(datain[0]),length(datain));
  response := Sysutils.TEncoding.GetEncoding(1250).getString(datain);

   //TStringStream and TStringList can use encoding for I/O operations
   stringList:TStringList.create;
   stringList.text := hello;
   stringList.saveToFile('file.txt',SysUtils.TEncoding.Unicode);
   stringList.destroy;
   stringStream := TStringStream(hello,SysUtils.TEncoding.Unicode);
   stringStream.saveToFile('file2.txt');
   stringStream.Destroy;
end;


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow