Строку в массив байтов в UTF-8?
Как преобразовать WideString (или другую длинную строку) в массив байтов в UTF-8?
6 ответов
такая функция сделает то, что вам нужно:
function UTF8Bytes(const s: UTF8String): TBytes;
begin
Assert(StringElementSize(s)=1);
SetLength(Result, Length(s));
if Length(Result)>0 then
Move(s[1], Result[0], Length(s));
end;
вы можете вызвать его с любым типом строки, и RTL преобразует из кодировки строки, которая передается в UTF-8. Поэтому не обманывайте себя, думая, что вы должны преобразовать в UTF-8 перед вызовом, просто передайте любую строку и позвольте RTL делать работу.
после этого это довольно стандартная копия массива. Обратите внимание на утверждение, которое явно вызывает предположение о размере строкового элемента для кодированного UTF-8 строка.
Если вы хотите получить нулевой Терминатор, вы напишете его так:
function UTF8Bytes(const s: UTF8String): TBytes;
begin
Assert(StringElementSize(s)=1);
SetLength(Result, Length(s)+1);
if Length(Result)>0 then
Move(s[1], Result[0], Length(s));
Result[high(Result)] := 0;
end;
если вы используете Delphi 2009 или более позднюю версию (версии Unicode), преобразование WideString в UTF8String-это простая инструкция присваивания:
var
ws: WideString;
u8s: UTF8String;
u8s := ws;
компилятор вызовет правильную библиотечную функцию для преобразования, потому что он знает, что значения типа UTF8String имеют "кодовую страницу"CP_UTF8
.
в Delphi 7 и более поздних версиях вы можете использовать предоставленную функцию библиотеки Utf8Encode
. Для еще более ранних версий вы можете получить эту функцию из других библиотек, таких как в JCL.
вы также можете написать свою собственную функцию преобразования с помощью Windows API:
function CustomUtf8Encode(const ws: WideString): UTF8String;
var
n: Integer;
begin
n := WideCharToMultiByte(cp_UTF8, 0, PWideChar(ws), Length(ws), nil, 0, nil, nil);
Win32Check(n <> 0);
SetLength(Result, n);
n := WideCharToMultiByte(cp_UTF8, 0, PWideChar(ws), Length(ws), PAnsiChar(Result), n, nil, nil);
Win32Check(n = Length(Result));
end;
много времени вы можете просто использовать UTF8String в качестве массива, но если вам действительно нужен массив байтов, вы можете использовать функции Дэвида и Космина. Если вы пишете свою собственную функцию преобразования символов, вы можете пропустить UTF8String и перейти непосредственно к массиву байтов; просто измените тип возврата на TBytes
или array of Byte
. (Вы также можете увеличить длину на единицу, если вы хотите, чтобы массив был null-terminated. SetLength сделает это для строки неявно, но для массива.)
если у вас есть какой-то другой тип строки, который не является ни WideString, UnicodeString, ни UTF8String, то способ преобразовать его в UTF-8-это сначала преобразовать его в WideString или UnicodeString, а затем преобразовать его обратно в UTF-8.
var S: UTF8String;
B: TBytes;
begin
S := 'Șase sași în șase saci';
SetLength(B, Length(S)); // Length(s) = 26 for this 22 char string.
CopyMemory(@B[0], @S[1], Length(S));
end.
в зависимости от того, для чего вам нужны байты, вы можете включить нулевой Терминатор.
для производственного кода убедитесь, что вы проверяете пустую строку. Добавление требуемого 3-4 LOC просто затруднит чтение образца.
У меня есть следующие две подпрограммы (исходный код можно скачать здесь -http://www.csinnovations.com/framework_utilities.htm):
функция CsiBytesToStr(const pInData: TByteDynArray; pStringEncoding: TECsiStringEncoding; pIncludesBom: Boolean): string;
функция CsiStrToBytes(const pInStr: строка; pStringEncoding: TECsiStringEncoding; pIncludeBom: Boolean): TByteDynArray;
widestring - > UTF8:
http://www.freepascal.org/docs-html/rtl/system/utf8decode.html
противоположную:
http://www.freepascal.org/docs-html/rtl/system/utf8encode.html
обратите внимание, что назначение widestring ansistring в системе pre D2009 (включая текущий бесплатный Pascal) преобразуется в локальную кодировку ansi, искажая символы.
для части TBytes см. замечание Роба Кеннеди сверху.