Нет причины, по которой вам пришлось бы менять строку 121 ZLibEx.pas ; это верно для всех версий Delphi, включая Delphi 2009. Символ UNICODE
должен only быть определен для Delphi 2009, а когда это так, определения типов для RawByteString
, UnicodeString
и UnicodeChar
все должны быть пропущены, потому что они уже являются внутренними типами в языке.
ZCompressStr
создаст строку, которая может содержать непечатаемые символы, включая нулевые байты. Он сохраняет свой результат в RawByteString
, который Delphi обрабатывает специально.
TStringList
, как и все остальное в Delphi 2009, использует Unicode. Свойство Text
имеет тип UnicodeString
. Когда вы присваиваете любое отличное от UnicodeString
значение UnicodeString
, вы получаете преобразование из функции API MultiByteToWideStr
. Даже RawByteString
включено в это правило. Если вы не присвоили строковое значение для кодовой страницы RawByteString
, тогда у него будет кодовая страница 0, которая является CP_ACP
, кодовой страницей по умолчанию для вашей системы.
Если строка на самом деле не содержит символов, закодированных в соответствии с системной кодовой страницей, то любое преобразование вызывает проблемы: мусор внутри, мусор вне. В частности, нет гарантии, что вы получите такое же количество символов.
Как упоминал Smok1 , TStringList.Text
является собственностью. У него есть метод установки, который разбивает данную строку на отдельные строки. Когда вы читаете свойство, оно снова объединяет все эти строки в одну строку. В то время как устанавливает свойство, TStrings.SetTextStr
(в Classes.pas , если вам интересно) будет разбивать строку в любом случае #0
, #10
или #13
. То есть нулевые символы, переводы строки и возврат каретки. При повторном соединении всех строк он будет использовать свое свойство LineBreak
, которое инициализируется глобальной переменной sLineBreak
. Разрыв строки также ставится после последней строки, поэтому каждая строка заканчивается LineBreak
. Таким образом, преобразование не обязательно в оба конца.
Итак, из этого можно извлечь две вещи:
- Не обрабатывать сжатые данные как текст.
- Не используйте
TStrings
потомков для хранения вещей, которые вы не хотите обрабатывать несколькими строками.
Еще один хороший совет: не используйте string
как общий тип хранения данных. Используйте его только для реального текста. Для хранения произвольных двоичных данных предпочтите TBytes
или TMemoryStream
. Используя ваш пример, вы можете сжать строку следующим образом:
var
ss: TStream;
ms: TMemoryStream;
begin
ss := TStringStream.Create('text');
try
ms := TMemoryStream.Create;
try
ShowMessage(IntToStr(ss.Size));
ZCompressStream(ss, ms);
ShowMessage(IntToStr(ms.Size));
finally
ms.Free;
end;
finally
ss.Free;
end;
end;