Я преобразовываю программу D2006 в D2010. Мне сохранили значение в единственном байте на символьную строку в моей базе данных, и я должен загрузить его в управление, которое имеет LoadFromStream, таким образом, мой план состоял в том, чтобы записать строку в поток и использование это с LoadFromStream. Но это не работало. В изучении проблемы я вижу проблему, которая говорит мне, что я действительно не понимаю, как преобразование от AnsiString до Unicode представляет работы в виде строки. Вот часть автономного кода, который иллюстрирует проблему, которой я смущен:;
procedure TForm1.Button1Click(Sender: TObject); {$O-}
var
sBuffer: String;
oStringStream: TStringStream;
sAnsiString: AnsiString;
sUnicodeString: String;
iSize1,
iSize2: Word;
begin
sAnsiString := '12345';
oStringStream := TStringStream.Create(sBuffer);
sUnicodeString := sAnsiString;
iSize1 := StringElementSize(sAnsiString);
iSize2 := StringElementSize(sUnicodeString);
oStringStream.WriteString(sUnicodeString);
end;
Если Вы повредитесь на последней строке и осмотрите свойство Bytes oStringStream, то Вы будете видеть, что это похоже на это:
Bytes (49 {$31}, 50 {$32}, 51 {$33}, 52 {$34}, 53 {$35}
Я ожидал, что это могло бы посмотреть что-то как
(49 {$31}, 00 {$00}, 50 {$32}, 00 {$00}, 51 {$33}, 00 {$00},
52 {$34}, 00 {$00}, 53 {$35}, 00 {$00} ...
По-видимому, мои ожидания по ошибке. Но затем, как преобразовать AnsiString в unicode?
Я не вытаскиваю правильные результаты из LoadFromStream, потому что он читает из потока два байта за один раз, но данные, которые он получает, не расположены тот путь. Что я должен сделать, чтобы дать LoadFromStream хорошо сформированный поток данных на основе строки unicode?
Спасибо за помощь.
Каков тип параметра oStringStream.WriteString? Если это AnsiString, у вас есть неявное преобразование из Unicode в Ansi, и это объясняет ваш пример.
Обновлено: теперь реальный вопрос заключается в том, как TStringStream хранит данные внутри. В следующем примере кода (Delphi 2009)
procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
SS: TStringStream;
begin
S:= 'asdfg';
SS:= TStringStream.Create(S); // 1 byte per char
SS.WriteString('321');
Label1.Caption:= SS.DataString;
SS.Free;
end;
TStringStream использует внутреннюю системную кодировку ANSI по умолчанию (1 байт на символ). {{ 1}} Конструктор и процедуры WriteString преобразуют строковый аргумент из Unicode в ANSI.
Чтобы переопределить это поведение, вы должны явно объявить кодировку в конструкторе:
procedure TForm1.Button1Click(Sender: TObject);
var
S: string;
SS: TStringStream;
begin
S:= 'asdfg';
SS:= TStringStream.Create(S, TEncoding.Unicode); // 2 bytes per char
SS.WriteString('321');
Label1.Caption:= SS.DataString;
SS.Free;
end;
Я думаю, вы хотите использовать:
LoadFromStream(stream, TEncoding.ASCII);
Если ваш однобайтовый текст не ASCII, а основан на кодовой странице, то может подойти следующее:
LoadFromStream(stream, TEncoding.GetEncoding(1252));
где "1252" - кодовая страница, на которой основан ваш однобайтовый текст.
Формат потока в значительной степени зависит от TStringStream.Encoding. В вашем примере используемая кодовая страница должна быть такой же, как и sBuffer (см. импликацию из TStringStream.Create).
Поскольку oStringStream.WriteString(sUnicodeStream);
, похоже, сохраняет как отдельные байты, я бы предположил, что sBuffer - это Ansistring или RawByteString.
Теперь... почему происходят сбои при чтении... Вы так и не привели пример того, как вы выполняете обратное чтение в этом потоке.