2016-07-04 2 views
2

По старым причинам мне нужно использовать старый источник, который использует AnsiString вместо UnicodeString в Rad Studio.Понимание UTF8Encode и UTF8ToString в Rad Studio

Итак, мой план состоит в том, чтобы использовать String большую часть времени, и просто, когда мне нужно использовать эту библиотеку, конвертируйте в AnsiString и то же самое из AnsiString в String как можно скорее.

String temp = L"汉语/漢語"; 
AnsiString raw=UTF8Encode(temp); 
String dest = UTF8ToString(raw); 

Когда я проверяю, я получаю ??? вместо 汉语/漢語. Что я делаю неправильно?

+1

Что вы делаете неправильно, используется 'AnsiString'. Вам нужно прекратить это делать. Вам нужно хранить данные в кодировке Unicode. ANSI не выполнит свою работу. Либо UTF-16, либо UTF-8, но не ANSI. Без какого-либо знания устаревших мотивов трудно сказать вам решение. –

+0

Я знаю это, но проблема в том, что в старой библиотеке AnsiString используется для хранения двоичных данных, в данном случае UTF8. Мне нужно будет переписать всю библиотеку, поэтому я пытаюсь использовать ее без критических изменений. Я думал, что могу продолжать использовать AnsiString для хранения двоичных данных без преобразования страницы. Разве это невозможно? – kokokok

+0

Я не знаю достаточно о эмуляции C++ Builder строк Delphi, но в Delphi я бы использовал 'UTF8String' для кодированного текста UTF-8 и' TBytes' для двоичных данных. Я бы потратил время на реорганизацию этого. Обратите внимание, что (по крайней мере, в Delphi) вы можете напрямую конвертировать между 'UTF8String' и' UnicodeString' без каких-либо потерь. –

ответ

2

Вам необходимо избегать использования AnsiString в качестве двоичного буфера в Delphi/C++ Builder 2009 и более поздних версиях. Это кодированная строка, и это может привести к получению тонких/неожиданных преобразований данных из одной кодовой страницы в другую по мере прохождения строки. В вашем случае ??? является прямым результатом данных, фактически преобразованных в кодовую страницу Ansi, которая не поддерживает символы Unicode, которые вы пытаетесь использовать.

Вы действительно должны использовать TBytes для двоичных данных. Для UTF-8 закодированной строки, используйте UTF8String вместо:

String temp = L"汉语/漢語"; 
UTF8String raw = UTF8String(temp); 
... 
String dest = String(raw); 

С учетом сказанного, так как вы должны Interop с 3-сторонней библиотеки, ожидающий UTF-8 кодируются AnsiString как двоичный буфер , то вы можете по крайней мере использовать UTF8String переменной и тип-брось (не назначать его), чтобы AnsiString при прохождении его в библиотеку:

library_function(*(reinterpret_cast<AnsiString*>(&raw)); 

Или:

library_function(reinterpret_cast<AnsiString&>(raw)); 

Это работает, потому что AnsiString, UTF8String и RawByteString все они основаны на том же типе AnsiStringT основания:

typedef AnsiStringT<0> AnsiString; 
typedef AnsiStringT<65001> UTF8String; 
typedef AnsiStringT<65535> RawByteString; 

и таким образом все разделяют общий макет памяти и реализации под капотом, и Delphi будет принимать это просто хорошо.

Если вы хотите быть действительно приключений, вы должны обновить библиотеку, чтобы использовать RawByteString или UTF8String (если не TBytes) вместо AnsiString, то вам не нужен тип-бросок на всех :

library_function(raw); 

: вам действительно нужно получить новую версию этой библиотеки или использовать другую библиотеку.

: Это тип ситуации, изначально предназначавшийся для RawByteString.Он никогда не предназначался для использования для автономных переменных, но для параметров функций, которые могут принимать любой тип 8-битовой строки в качестве входных данных без выполнения преобразования данных.

0

В настоящем время, я нашел решение:

AnsiString UTF8ToBin(UTF8String value) 
{ 
    AnsiString dest; 
    dest.SetLength(value.Length()); 
    memcpy(dest.c_str(), value.c_str(), value.Length()); 
    return dest; 
} 

Это позволяет мне использовать библиотеку, используя тип AnsiString для хранения двоичных данных, в этом случае, UTF8.

Мне очень ясно, что мне нужно будет использовать TBytes для двоичных данных, но я не мог переписать библиотеку.

+2

Почему бы просто не использовать 'RawByteString' as-is вместо' AnsiString'? Присвоение 'UTF8String' в' RawByteString' сохраняет данные. Присвоение 'UTF8String'' AnsiString' не делает. 'RawByteString raw = UTF8Encode (temp);' или даже 'RawByteString raw = UTF8String (temp);' поскольку 'UTF8Encode()' устарел. Если библиотека принимает только «AnsiString» специально, а не «RawByteString» в общем случае, вы всегда можете использовать тип: 'UTF8String raw = temp; (* (AnsiString *) &raw); '' '' '' '' ''' '' '' '' (Ansi | Utf8 | Raw) String' использует общий формат памяти и реализацию, поскольку все они основаны на' AnsiStringT'. –

+0

Большая библиотека '(AnsiString *) & raw) 'Это еще одно решение. Спасибо. – kokokok

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