2015-08-31 2 views
0

В Delphi 7, у меня есть WideString, закодированные с Base64 (Это я получил от веб-службы с WideString результата):Delphi 7 и декодировать UTF-8 base64

PD94bWwgdmVyc2lvbj0iMS4wIj8 + DQo8c3RyaW5nPtiq2LPYqjwvc3RyaW5nPg ==

когда я декодирую его, что результат не UTF-8:

<?xml version="1.0"?> 
<string>طھط³طھ</string> 

Но когда я декодирую его base64decode.org, результат справедлив:

<?xml version="1.0"?> 
<string>تست</string> 

У меня есть функция EncdDecd для функции DecodeString.

+0

Связанный вопрос: [Как кодировать строки с библиотекой EncdDec] (http://stackoverflow.com/questions/21883152/how-to-encode-strings-with-encddec-library) – fantaghirocco

ответ

4

Проблема заключается в том, что вы используете DecodeString. Эта функция в Delphi 7 рассматривает декодированные двоичные данные как кодированные ANSI. И проблема в том, что ваш текст кодируется UTF-8.

Для продолжения работы с блоком EncdDecd у вас есть несколько вариантов. Вы можете переключиться на DecodeStream. Например, этот код будет производить UTF-8, закодированный текстовый файл с данными:

{$APPTYPE CONSOLE} 

uses 
    Classes, 
    EncdDecd; 

const 
    Data = 'PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c3RyaW5nPtiq2LPYqjwvc3RyaW5nPg=='; 

var 
    Input: TStringStream; 
    Output: TFileStream; 

begin 
    Input := TStringStream.Create(Data); 
    try 
    Output := TFileStream.Create('C:\desktop\out.txt', fmCreate); 
    try 
     DecodeStream(Input, Output); 
    finally 
     Output.Free; 
    end; 
    finally 
    Input.Free; 
    end; 
end. 

Или вы могли бы продолжать DecodeString, но затем сразу же декодировать текст UTF-8 в WideString. Как это:

{$APPTYPE CONSOLE} 

uses 
    Classes, 
    EncdDecd; 

const 
    Data = 'PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8c3RyaW5nPtiq2LPYqjwvc3RyaW5nPg=='; 

var 
    Utf8: AnsiString; 
    wstr: WideString; 

begin 
    Utf8 := DecodeString(Data); 
    wstr := UTF8Decode(Utf8); 
end. 

Если содержимое файла может быть представлена ​​в преобладающих ANSI локали вашего приложения, то вы можете конвертировать, что WideString в простой AnsiString.

var 
    wstr: WideString; 
    str: string; // alias to AnsiString 
.... 
wstr := ... // as before 
str := wstr; 

Однако, я не думаю, что с помощью ANSI закодированный текст будет вести к очень плодотворной жизни программирования. Я призываю вас принять решения Unicode.

Судя по содержанию декодированных данных, это XML. Обычно передается XML-парсеру. Большинство синтаксических анализаторов XML будут принимать кодированные данные UTF-8, поэтому вы, вероятно, можете дешифровать base64 в потоке памяти, используя DecodeStream, а затем передать этот поток вашему парсеру XML. Таким образом, вам не нужно расшифровывать UTF-8 в текст и позволить парсеру XML иметь дело с этим аспектом.

+0

+1 И это стоит что UTF-8 является решением Unicode, даже для более старых версий Delphi, поскольку OP все еще использует. Http: //www.utf8everywhere.org/Для простого процесса использование WideString - это решение; но он имеет производительность (поскольку распределение памяти BSTR очень плохое). Вы можете использовать специальные функции или классы UTF-8, при необходимости Delphi 7 для более крупного проекта. –

+0

@ArnaudBouchez Согласен. Я, конечно, не имел в виду, что UTF-8 не является Unicode. –

+2

Обратите внимание, что 'UTF8Decode()' (и 'UTF8Encode()') был взломан в старых версиях Delphi, включая v7. Это была не полная реализация UTF-8, например, она не могла обрабатывать последовательности UTF-8 выше 3 байтов. Наконец, он был исправлен в D2009 (избавляясь от их ручной реализации UTF-8 и позволяя ОС делать кодирование/декодирование). –

1

В качестве дополнения к удивительному ответу Дэвид Хеффернэн, и записке Реми Лебо о том, как он ломал на Delphi 7, я хотел бы добавить функцию, которая поможет любому разработчику наклеенного на Delphi 7.

Поскольку UTF8Decode() сломан в Delphi 7, я нашел функцию в forum, что решить мою проблему:

function UTF8ToWideString(const S: AnsiString): WideString; 
var 
    BufSize: Integer; 
begin 
    Result := ''; 
    if Length(S) = 0 then Exit; 
    BufSize := MultiByteToWideChar(CP_UTF8, 0, PAnsiChar(S), Length(S), nil, 0); 
    SetLength(result, BufSize); 
    MultiByteToWideChar(CP_UTF8, 0, PANsiChar(S), Length(S), PWideChar(Result), BufSize); 
end; 

Итак, теперь вы можете использовать DecodeString, а затем декодировать текст UTF-8 в WideString с помощью этой функции:

begin 
    Utf8 := DecodeString(Data); 
    wstr := UTF8ToWideString(Utf8); 
end. 
Смежные вопросы