Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Base64 кодирование и UnicodeString [WinXP]


DVM ©   (2008-09-30 12:19:00) 

Никак не пойму как правильно закодировать в Base64 Unicode строку (ту что в Delphi 2009 теперь string).

Т.е. допустим имеем строку

var s: string;
...
s:='йцукен';
Беру TIdEncoderMIME из Indy что в Delphi 2009, кодирую получаю:
OUZDOjU9

Как так может быть, ведь строка занимает 12 байт, а не 6 ?

Тот же самый кодер для строки qwerty дает cXdlcnR5.

В Indy ошибка или нет?

Unicode строку надо кодировать как буфер с длиной Length(s) * SizeOf(Char) или как то по другому?


Eraser   (2008-09-30 20:19:00) [1]

> [12] DVM ©   (30.09.08 18:09)

так точно.
проблема тут
function TIdEncoder.Encode(const AIn: string): string;
var
 LStream: TMemoryStream;
begin
 if AIn<>'' then  begin
   LStream := TMemoryStream.Create;
   try
     IdGlobal.WriteStringToStream(LStream,AIn, en8bit ); // <<-------------------
     LStream.Position := 0;
     Result := Encode(LStream);
   finally
     FreeAndNil(LStream);
   end;
 end else begin
   Result := '';
 end;
end;


Anatoly Podgoretsky   (2008-09-30 19:17:00) [2]


> Т.е. выходит Indy не поддерживает Unicode.

Может и не поддерживает, поскольку Инди это не Дельфи, а взят на халяву у Nevrona.
Надо смотреть исходники функции TIdEncoderMIME


DVM   (2008-09-30 18:09:00) [3]

Т.е. в библиотеках Indy не поправили код насчет Unicode.

А вот зато стандартный дельфовый EncdDecd поправили. С ним нет проблем.


DVM   (2008-09-30 18:07:00) [4]


> Anatoly Podgoretsky ©   (30.09.08 15:19) [7]
>
> > DVM  (30.09.2008 14:25:04)  [4]
>
> Инди кодирует правильно, проверено опытами. Это ты что то
> неправильно делаешь, должно получиться 16 байт, но не AnsiChar
> - а просто 16 байт в формате Base64
>

судя по описанию функции должен получиться на выходе кодера именно string.


> Простой вопрос, может ламерский, а Дельфи у тебя какая?

2009.


> Eraser ©   (30.09.08 15:45) [9]
>
> вот корректный код для Делфи.

Так, да все верно выходит, то же самое можно и по старинке типа того:

var
s1: string;
Bytes: PAnsiChar;
begin
s1 := 'йцукен';
GetMem(Bytes, Length(s1) * SizeOf(Char));
try
  Move(s1, Bytes, Length(s1) * SizeOf(Char));
  ShowMessage(IdEncoderMIME1.EncodeString(Bytes));
finally
  FreeMem(Bytes, Length(s1) * SizeOf(Char));
end;
end;


но почему так вот неверно мне чего-то не понятно:

procedure TForm1.Button1Click(Sender: TObject);
begin
 edit2.Text := IdEncoderMIME1.EncodeString(edit1.text);
end;

Т.е. выходит Indy не поддерживает Unicode.


Anatoly Podgoretsky   (2008-09-30 16:14:00) [5]

> Eraser  (30.09.2008 15:18:06)  [6]

Инди не работает с Юникод, но и Base64 не имеет никакого отношения к Юникод.


Eraser   (2008-09-30 15:45:00) [6]

вот корректный код для Делфи.
procedure TForm1.Button1Click(Sender: TObject);
var
 s1: string;
 Bytes: TBytes;
begin
 s1 := 'йцукен';

 // Кодирование.
 Bytes := TEncoding.Unicode.GetBytes(s1);
 s1 := IdEncoderMIME1.EncodeBytes(Bytes);
 ShowMessage(s1);

 // Декодирование.
 Bytes := IdDecoderMIME1.DecodeBytes(s1);
 s1 := TEncoding.Unicode.GetString(Bytes);
 ShowMessage(s1);
end;


Anatoly Podgoretsky   (2008-09-30 15:21:00) [7]

Простой вопрос, может ламерский, а Дельфи у тебя какая?


Anatoly Podgoretsky   (2008-09-30 15:19:00) [8]

> DVM  (30.09.2008 14:25:04)  [4]

Инди кодирует правильно, проверено опытами. Это ты что то неправильно делаешь, должно получиться 16 байт, но не AnsiChar - а просто 16 байт в формате Base64


Eraser   (2008-09-30 15:18:00) [9]

хм..
на C# подобный код вернул "OQRGBEMEOgQ1BD0E".

       private void button1_Click(object sender, EventArgs e)
       {
           string s1 = "йцукен";

           // Кодирование.
           byte[] toEncodeAsBytes = System.Text.UnicodeEncoding.Unicode.GetBytes(s1);
           textBox1.Text = Convert.ToBase64String(toEncodeAsBytes);

           // Декодирование.
           toEncodeAsBytes = Convert.FromBase64String(textBox1.Text);
           s1 = System.Text.UnicodeEncoding.Unicode.GetString(toEncodeAsBytes);
           MessageBox.Show(s1);
       }

очень странно, вроде Indy работает с string (в т.ч. записывает в поток), нигде упоминаний про ansistring не видел...


Anatoly Podgoretsky   (2008-09-30 15:17:00) [10]

> DVM  (30.09.2008 13:55:02)  [2]

Вообще то это размер любой строки, как Юникод, так и нет, и если заменить char на тип, то это будет работать и для динамических массивов.

AnsiString надо было использовать и ранее и это не связано с Д2009, по крайней мере это описано уже в Д2


DVM   (2008-09-30 14:25:00) [11]


> Anatoly Podgoretsky ©   (30.09.08 14:17) [3]


> Base64 не строковая функция.

это я понимаю, получается Indy кодирует неправильно, т.к. из шести символов Unicode строки (12 байт) не может получиться 8 символов AnsiChar (8 байт). А вот получается.

Кстати, а WEB сервера принимают GET запросы только в однобайтной кодировке?


Anatoly Podgoretsky   (2008-09-30 14:17:00) [12]

> DVM  (30.09.2008 12:19:00)  [0]

Для Base64 совсем не важно строка ли это и если строка, то какого типа. Base64 не строковая функция.


DVM   (2008-09-30 13:55:00) [13]


> но размер буфера нужно выделять как
> Length(s)*SizeOf(WideChar)+1

Я не выделяю память. Length(s) * SizeOf(Char) - это количество памяти, занимаемое Unicode строкой.


> По умолчанию в D2009 String уже UnicodeString, поэтому если
> нужно
> использовать однобайтовую строку, то описывать нужно как
> AnsiString

Да это понятно, с Ansistring проблем нет, кроме кучи варнингов насчет потенциально возможной потери данных.


tytus   (2008-09-30 13:44:00) [14]

Не знаю как в Indy10, потому как не кодировал в Base64,
но размер буфера нужно выделять как
Length(s)*SizeOf(WideChar)+1

По умолчанию в D2009 Stringуже UnicodeString, поэтому если нужно
использовать однобайтовую строку, то описывать нужно как AnsiString


Наверх

Титульная страница Поиск, карта сайта Написать письмо