2010-11-04 4 views
12

Я пишу класс, который сохранит широкие строки в двоичном файле. Я использую Delphi 2005 для этого, но приложение будет позже портирована на Delphi 2010. Я чувствую себя очень уверены здесь, кто-то может подтвердить, что:Delphi WideString и Delphi 2009+

  1. Delphi 2005 WideStringэто точно тот же тип как Delphi 2010 String

  2. Delphi 2005 WideString полукокса, а также Delphi 2010 String полукокса гарантированно всегда быть 2 байта.

Со всеми Unicode форматирует там я не хочу, чтобы ударить с одним из символов в моей струна вдруг быть 3 байта в ширину или что-то подобное.

Edit: Нашел:... «Я сказал UnicodeString, не WideString WideString до сих пор существует, и остается неизменным WideString выделяется менеджером памяти Windows, и следует использовать для взаимодействия с COM-объектами WideString карты прямо к типу BSTR в COM. " по адресу http://www.micro-isv.asia/2008/08/get-ready-for-delphi-2009-and-unicode/

Теперь я еще более смущен. Итак, Delphi 2010 WideString отличается от Delphi 2005 WideString? Должен ли я использовать UnicodeString?

Редактировать 2: В Delphi 2005 нет типа UnicodeString. FML.

+2

Почему бы вы сделать вывод, что Delphi 2010 WideString не то же самое, как Delphi 2005 WideString после прочтения заявления что «WideString все еще существует и не изменяется»? –

ответ

1
  1. Delphi 2005 WideString точно такой же тип, как Delphi 2010 Струнный

Это не так - бывший Delphi 2010 строка имеет скрытый внутреннее поле кодовой страницы - но, вероятно, это не имеет значения для вас.

  1. Алфавит Delphi 2005 WideString, а также символ String Delphi 2010 гарантированно будет иметь размер 2 байта.

Это правда. В Delphi 2010 SizeOf (Char) = 2 (Char = WideChar).


Там не может быть другими кодовой юникод строк - поле кодового было введено, чтобы создать общий двоичный формат для обоего строк ANSI (что поле необходимо кодовое) и строку Unicode (которые не нужно).

Если вы сохраните данные WideString для потока в Delphi 2005 и загрузите одни и те же данные в строку в Delphi 2010, все должно работать нормально.

WideString = BSTR и что не изменилось между Delphi 2005 и 2010

UnicodeString = WideString в Delphi 2005 (если в Delphi 2005 Тип UnicodeString существует - я не знаю) UnicodeString = строку в Delphi 2009 и выше.


@Marco - Ansi и Unicode строки в Delphi 2009+ имеют общий двоичный формат (заголовок 12 байт).

Кодовая страница UnicodeString CP_UTF16 = 1200;

+0

Итак, если я сохраню WideString в Delphi 2005, используя Stream.Write (AWideString [1], 2 * Length (AWideString)), и он загружается с версией приложения Delphi 2010, которая использует другую кодовую страницу, что произойдет? Должен ли я сохранять кодовую страницу вместе со строками? – David

+0

Вы не можете рассчитывать на SizeOf (Char) = 2 для будущей версии, поэтому не используйте 2, но используйте SizeOf (Char). Мы заняты переносом старого кода на 2010 год, и есть много (SizeOf (Char) = 1) предположений, которые сводят нас с ума. –

+0

Мне не известно о том, что у Tunicodestring было поле кодовой страницы? Я думал, что только у нас есть? –

12

Для вашего первого вопроса: WideString не совсем тот же тип, что и D2010's string. WideString - это тот же тип COM BSTR, что и всегда. Он управляется Windows, без подсчета ссылок, поэтому он копирует весь BSTR каждый раз, когда вы его передаете.

UnicodeString, который по умолчанию строка типа в D2009 и на, в основном версия AnsiString все мы знаем и любим UTF-16. У него есть счетчик ссылок и управляется компилятором Delphi.

Для второго по умолчанию char тип теперь WideChar, которые являются теми же символами, которые всегда использовались в WideString. Это кодировка UTF-16, 2 байта на символ. Если вы сохраните данные WideString в файл, вы можете без проблем загрузить его в UnicodeString. Разница между этими двумя типами связана с управлением памятью, а не с форматом данных.

+0

Но в Delphi 2005 нет типа UnicodeString! Я дерьмо не повезло? Я не хочу использовать WideString, если это не то же самое, что строка Delphi 2010. – David

+0

@David: Проверьте последние два предложения. Строковые данные точно такие же. Другое дело, что 'UnicodeString' использует более эффективную модель управления памятью. –

+0

Unicodestring - это более или менее широкая часть Kylix. –

4

Как упоминалось выше, тип данных типа string (фактически UnicodeString) в Delphi 2009 и выше не эквивалентен типу данных WideString в предыдущих версиях, но формат содержимого данных одинаков. Оба они сохраняют строку в UTF-16. Поэтому, если вы сохраняете текст с помощью WideString в более ранних версиях Delphi, вы должны иметь возможность правильно его читать, используя строковый тип данных в последних версиях Delphi (2009 и выше).

Следует отметить, что производительность UnicodeString превосходит WideString. Поэтому, если вы собираетесь использовать один и тот же исходный код как в Delphi 2005, так и в Delphi 2010, я предлагаю вам использовать псевдоним типа string с условной компиляцией в вашем коде, чтобы вы могли использовать лучшее из обоих миров:

type 
    {$IFDEF Unicode} 
    MyStringType = UnicodeString; 
    {$ELSE} 
    MyStringType = WideString; 
    {$ENDIF} 

Теперь вы можете использовать MyStringType в качестве типа строки в исходном коде. Если компилятор является Unicode (Delphi 2009 и выше), то ваш тип строки будет алиасом типа UnicodeString, который представлен в Delphi 2009 для хранения строк Unicode. Если компилятор не является unicode (например, Delphi 2005), тогда ваш тип строки будет псевдонимом для старого типа данных WideString. И поскольку они оба являются UTF-16, данные, сохраненные в любой из версий, должны быть правильно прочитаны другим.

+10

Вместо определения нового имени строки вы можете сделать следующее: '{$ IFNDEF Unicode} type UnicodeString = WideString; {$ ENDIF}'. Таким образом, ваш код не усеян именем нестандартного типа. –

+0

Да, это было бы лучшим решением. Благодарю. – vcldeveloper

0

Правило простое:

  • Если вы хотите работать с юникод строк внутри модуля только - использовать UnicodeString типа (*).
  • Если вы хотите установить связь с COM или с другими кросс-модульными целями, используйте тип WideString.

Вы видите, WideString - особый тип, так как это не родной тип Delphi. Это псевдоним/обертка для BSTR - тип системной строки, предназначенный для использования с COM или межмодульными сообщениями. Будучи уникодом - это просто побочный эффект.

С другой стороны, AnsiString и UnicodeString - являются родными типами Delphi, которые не имеют аналога на других языках.String - это просто псевдоним для AnsiString или UnicodeString.

Итак, если вам нужно передать строку в другой код - используйте WideString, иначе - используйте либо AnsiString, либо UnicodeString. Просто.

P.S.

(*) Для старых Delphi - просто поместите

{$IFNDEF Unicode} 

type 
    UnicodeString = WideString; 

{$ENDIF} 

где-то в вашем коде. Это исправление позволит вам написать тот же код для любой версии Delphi.

0

Хотя символ D2010 всегда и ровно 2 байта, в символах UTF-16 присутствуют одни и те же функции сгибания и комбинирования символов, как и символы UTF-8. Вы не видите этого с узкими строками, потому что они основаны на кодировке, но с помощью строк в unicode возможно (и в некоторых ситуациях общее) иметь аффективные, но невидимые символы. Примеры включают в себя знак порядка байтов (BOM) в начале файла или потока unicode, символы слева направо/справа налево и огромный диапазон сочетания акцентов. Это в основном затрагивает вопросы о том, «сколько пикселей будет шириной этой строки на экране» и «сколько букв находится в этой строке» (в отличие от «количества символов в этой строке»), но также означает, t случайным образом измельчают символы из строки и предполагают, что они пригодны для печати. Такие операции, как «удалить последнюю букву из этого слова», становятся нетривиальными и зависят от используемого языка.

Вопрос о том, что «один из символов в моей строке внезапно имеет длину 3 байта», отражает небольшое недоумение о том, как работает UTF. Возможно (и действительно) взять три байта в строке UTF-8, чтобы представить один печатный символ, но каждый байт будет действительным символом UTF-8. Скажем, письмо плюс два сочетания акцентов. Вы не получите символ в UTF-16 или UTF-32 длиной 3 байта, но может иметь длину 6 байтов (или 12 байтов), если он представлен с использованием трех кодовых точек в UTF-16 или UTF-32. Это приводит нас к нормализации (или нет).

Но при условии, что вы имеете дело со струнами как целыми вещами, все это очень просто - вы просто берете строку, записываете ее в файл, а затем читаете ее обратно. Вам не нужно беспокоиться о штрафе печать строкового отображения и манипуляции, все это обрабатывается операционной системой и библиотеками. Строки. LoadFromFile (имя) и Listbox.Items.Add (строка) работают точно так же в D2010, как и в D2007, все файлы unicode прозрачны для вас как программиста.

0

Я пишу класс, который будет сохранять широкие строки в двоичный файл.

Когда вы пишете класс в D2005 вы будете использовать WideString При переходе на D2010 WideString все еще будет действовать и работать должным образом. Widestring в D2005 такой же, как WideString в D2010.

Тот факт, что String = WideString в D2010 не нужно учитывать, поскольку компилятор имеет дело с этими проблемами легко.

Ваш вклад рутина, чтобы сохранить с (AString: String) нужно только одну строку ввода процедурный

procedure SaveAStringToBIN_File(AString:String); 
var wkstr : Widestring; 
begin 
{$IFDEF Unicode} wkstr := AString;  
{$ELSE}   wkstr := UTF8Decode(AString); {$ENDIF} 
... 
    the rest is the same saving a widestring to a file stream 
    write the length (word) of string then data 

end; 
Смежные вопросы