Сейчас, наверное, знающие люди скажут мне, что "дурная голова рукам покоя не даёт", но тем не менее...
Возникла следующая проблема:
Пусть есть строка S1 в UTF8 кодировке,
хочу получить строку S2 в UTF16
Вроде бы
- Код: Выделить всё
Utf8ToUnicode(s2, s1, Length(s1))
должен осуществлять задуманное, однако, в моём случае (WinXP, Lazarus 9.27 svn 19575), в S2 мы имеем текст в кодировке Win-1251
Поскольку "не царское это дело" — разбираться в чужих кодах
![Smile :)](./images/smilies/icon_smile.gif)
- Код: Выделить всё
unit My_UniCode;
interface
const
BESign:string=#$FE#$FF; // Сигнатура для файла с BigEndian последовательностью кодирования, вроде бы, должна использоваться по умолчанию.
LESign:string=#$FF#$FE; // Однако весёлые ребята из МелкоСофта, похоже, предпочитают LittleEndian
UTF8Sign:String=#$EF#$BB#$BF; // Сигнатура для UTF8 файла
function Utf8ToUtf16BE(s:string):string;
function Utf8ToUtf16LE(s:string):string;
function Utf16BETOUtf8(s:string):string;
function Utf16LETOUtf8(s:string):string;
implementation
function Utf8ToUtf16BE(s:string):string;
var
i, j, MaxI:integer;
b:byte;
begin
MaxI:=Length(s);
SetLength(Result, MaxI*4); // на 4 умножаем, т.к. по стандарту 1 символ может кодироваться 1..4 байтами
i:=1;
j:=1;
While i<=MaxI do begin
b:=Byte(s[i]);
if (b and $7F)=b then begin
Byte(Result[j]):=0;
Byte(Result[j+1]):=b;
inc(j,2);
inc(i);
Continue
end;
if (b and $DF)=b then begin
Byte(Result[j]):=(b and $1F) shr 2;
Byte(Result[j+1]):=(b shl 6) or (Byte(s[i+1]) and $3F);
inc(j,2);
inc(i,2);
Continue
end;
if (b and $EF)=b then begin
Byte(Result[j]):=((b and $0F) shl 4) or ((Byte(s[i+1]) and $3F) shr 2);
Byte(Result[j+1]):=((Byte(s[i+1]) and $03) shl 6) or (Byte(s[i+2]) and $3F);
inc(i,3);
inc(j,2);
Continue
end;
if (b and $F7)=b then begin
{ Так преобразуют в Unicode
Byte(Result[j]):=0;
Byte(Result[j+1]):=((b and $07) shl 2) or ((Byte(s[i+1]) and $3F) shr 4);
Byte(Result[j+2]):=((Byte(s[i+1])) shl 4) or ((Byte(s[i+2]) and $3F) shr 2);
Byte(Result[j+3]):=((Byte(s[i+2]) and $03) shl 6) or (Byte(s[i+3]) and $3F);
}
b:=(((b and $07) shl 2) or ((Byte(s[i+1]) and $3F) shr 4))-1;
Byte(Result[j]):=$D8 or (b shr 2);
Byte(Result[j+1]):=(b shl 6) or ((Byte(s[i+1]) and $0F) shl 2) or ((Byte(s[i+2]) and $3F) shr 4);
Byte(Result[j+2]):=$DC or ((Byte(s[i+2]) and $0C) shr 2);
Byte(Result[j+3]):=(Byte(s[i+2]) shl 6) or (Byte(s[i+2]) and $3F);
inc(i,4);
inc(j,4);
Continue
end
end;
SetLength(Result, j-1)
end;
function Utf8ToUtf16LE(s:string):string;
var
i, j, MaxI:integer;
b:byte;
begin
MaxI:=Length(s);
SetLength(Result, MaxI*4);
i:=1;
j:=1;
While i<=MaxI do begin
b:=Byte(s[i]);
if (b and $7F)=b then begin
Byte(Result[j+1]):=0;
Byte(Result[j]):=b;
inc(j,2);
inc(i);
Continue
end;
if (b and $DF)=b then begin
Byte(Result[j+1]):=(b and $1F) shr 2;
Byte(Result[j]):=(b shl 6) or (Byte(s[i+1]) and $3F);
inc(j,2);
inc(i,2);
Continue
end;
if (b and $EF)=b then begin
Byte(Result[j+1]):=((b and $0F) shl 4) or ((Byte(s[i+1]) and $3F) shr 2);
Byte(Result[j]):=((Byte(s[i+1]) and $03) shl 6) or (Byte(s[i+2]) and $3F);
inc(i,3);
inc(j,2);
Continue
end;
if (b and $F7)=b then begin
b:=(((b and $07) shl 2) or ((Byte(s[i+1]) and $3F) shr 4))-1;
Byte(Result[j+3]):=$D8 or (b shr 2);
Byte(Result[j+2]):=(b shl 6) or ((Byte(s[i+1]) and $0F) shl 2) or ((Byte(s[i+2]) and $3F) shr 4);
Byte(Result[j+1]):=$DC or ((Byte(s[i+2]) and $0C) shr 2);
Byte(Result[j]):=(Byte(s[i+2]) shl 6) or (Byte(s[i+2]) and $3F);
inc(i,4);
inc(j,3);
Continue
end
end;
SetLength(Result, j-1)
end;
function Utf16BEToUtf8(s:string):string;
var
i, j, MaxI:integer;
b:byte;
w:word;
begin
MaxI:=Length(s);
SetLength(Result, MaxI*2); // UTF8 Не более 4 байт на символ, UTF16 - не менее 2
i:=1;
j:=1;
While i<=MaxI do begin
b:=Byte(s[i]);
if (b and $D8)=$D8 then begin
// четырехбайтовый UTF-16 символ
w:=b;
w:=(w shl 8) or Byte(s[i+1]);
// сформируем первые 4 бита (номер плоскости)
b:=Byte((w xor $D800) shr 6)+1;
Byte(Result[j]):=$F0 or byte(b shr 2);
Byte(Result[j+1]):=$80 or ((b and $03) shl 4) or byte((w and $003C) shr 4);
Byte(Result[j+2]):=$80 or byte((w and $0003) shl 4);
w:=Byte(s[i+2]);
w:=(w shl 8) or Byte(s[i+3]);
w:=w xor $DC00;
Byte(Result[j+2]):=Byte(Result[j+2]) or Byte((w and $03C0) shr 6);
Byte(Result[j+3]):=$80 or Byte(w and $003F);
inc(j,4);
inc(i,4)
end else begin
// двухбайтовый UTF-16 символ
w:=b;
w:=(w shl 8) or Byte(s[i+1]);
if w<$80 then begin
Byte(Result[j]):=Byte(w);
inc(j)
end;
if ((w>=$80) and (w<$800)) then begin
Byte(Result[j]):=$C0 or Byte(w shr 6);
Byte(Result[j+1]):=$80 or Byte(w and $3F);
inc(j,2)
end;
if ((w>=$800) and (w<=$FFFF)) then begin
Byte(Result[j]):=$E0 or Byte(w shr 12);
Byte(Result[j+1]):=$80 or Byte((w and $03C0) shr 6);
Byte(Result[j+2]):=$80 or Byte(w and $3F);
inc(j,3)
end;
inc(i,2)
end
end;
SetLength(Result, j-1)
end;
function Utf16LEToUtf8(s:string):string;
var
i, j, MaxI:integer;
b:byte;
w:word;
begin
MaxI:=Length(s);
SetLength(Result, MaxI*2);
i:=1;
j:=1;
While i<=MaxI do begin
b:=Byte(s[i+1]);
if (b and $D8)=$D8 then begin
// четырехбайтовый UTF-16 символ
w:=b;
w:=(w shl 8) or Byte(s[i]);
// сформируем первые 4 бита (номер плоскости)
b:=Byte((w xor $D800) shr 6)+1;
Byte(Result[j]):=$F0 or byte(b shr 2);
Byte(Result[j+1]):=$80 or ((b and $03) shl 4) or byte((w and $003C) shr 4);
Byte(Result[j+2]):=$80 or byte((w and $0003) shl 4);
w:=Byte(s[i+3]);
w:=(w shl 8) or Byte(s[i+2]);
w:=w xor $DC00;
Byte(Result[j+2]):=Byte(Result[j+2]) or Byte((w and $03C0) shr 6);
Byte(Result[j+3]):=$80 or Byte(w and $003F);
inc(j,4);
inc(i,4)
end else begin
// двухбайтовый UTF-16 символ
w:=b;
w:=(w shl 8) or Byte(s[i]);
if w<$80 then begin
Byte(Result[j]):=Byte(w);
inc(j)
end;
if ((w>=$80) and (w<$800)) then begin
Byte(Result[j]):=$C0 or Byte(w shr 6);
Byte(Result[j+1]):=$80 or Byte(w and $3F);
inc(j,2)
end;
if ((w>=$800) and (w<=$FFFF)) then begin
Byte(Result[j]):=$E0 or Byte(w shr 12);
Byte(Result[j+1]):=$80 or Byte((w and $03C0) shr 6);
Byte(Result[j+2]):=$80 or Byte(w and $3F);
inc(j,3)
end;
inc(i,2)
end
end;
SetLength(Result, j-1)
end;
end.
Буду крайне признателен, если кто-нибудь всё-таки объяснит особоодарённому, как же эту задачку решают знающие люди. А то код всё-таки сыроватый (т.е. мою задачу здесь и сейчас, он, вроде бы, решает, а как он себя поведёт на каких-нибудь иероглифах...).