我有一个sqlite数据库(UTF-8编码)。在数据库中我有这样的记录(十六进制字节):
D0 9E D0 BA 29 F0 9F 92 8B F0 9F 92 8B
因此字节不是对齐的,即:
$D09E = O
$D0BA = к
$29 = )
$F09F928B = U+1F48b (KISS MARK)
$F09F928B = U+1F48b (KISS MARK)
这就是SQLite管理器中的样子:
但无论我做什么(UTF8Decode和一些自定义转换)我都无法在我启用Unicode的TNTStringGrid中显示它。
是的,我可以得到OK)?显示,但然后去Ок)рџ'<џџ'<或这是它看起来像真实(UTF8Encoded):РћРє)рџ'<рџ'<< / p>
我知道这是一个难题,但必须有一个解决方案,因为SQLite管理器显示它绝对正确。
那么如何显示那些U +字符和普通文字?
请帮忙! 3个昼夜与这项任务作斗争。
答案 0 :(得分:2)
您正在处理UTF“代理对”:
使用UTF-16,$ D800-DBFF和$ DC00-DCFF之间的值用于指定所谓的代理对。
使用这些代理对,我们可以映射10000美元或更高的Unicode代码点(在$ 10000到$ 10FFFD范围内)。
这是通过从值中减去$ 10000来完成的,保留0到$ FFFFD范围内的值,可以用20位表示。
这20位分为两对,每对10位,加到$ D800或。 $ DC00对。
因此,对于Unicode代码点$ 1D11E,UTF-16代理对计算如下:首先减去$ 10000,留下$ D11E,
这是20位的00001101000100011110,分为34美元和11美元。 $ 40增加到$ 800,$ 11E增加到$ DC00
导致最重要的代理人获得$ D834,而最不重要的代理人获得$ DD1E。
[请注意,Unicode代码点$ D800到$ DFFD将不会被Unicode标准指定为有效字符(以避免UTF-16出现问题),因此各个代理字符永远不会映射到实际字符本身(但是应始终用作一对)。]
另见http://en.wikipedia.org/wiki/UTF-16
要正确显示代理项对字符,您需要包含它们的字体。例如。 Windows字体Code2001,Euterpe,Free Serif,Musica,Quivira,Symbola支持U + 1D100 - U + 1D1FF(119040-119295)范围内的音乐符号(http://www.alanwood.net/unicode/fontsbyrange的.html#u1d100)
您需要在系统上下载并安装Musica字体(以前称为Musical Symbols)才能使此示例正常工作。下载位置例如http://users.teilar.gr/~g1951d/
[在Win7下安装:右键单击ttf文件并选择“安装”]
[测试页:http://www.alanwood.net/unicode/musical_symbols.html]
这是我使用上面的示例Delphi XE2测试代码(你有D2007,但这可能会让你上路)。
unit uSurrogatePairs;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TFrmSurrogatePairs = class(TForm)
MmoCharacter: TMemo;
Mmo: TMemo;
procedure FormShow(Sender: TObject);
private
procedure Log(S: String);
public
{ Public declarations }
end;
var
FrmSurrogatePairs: TFrmSurrogatePairs;
implementation
{$R *.dfm}
type
TDanishString = type ansistring(1252);
procedure TFrmSurrogatePairs.FormShow(Sender: TObject);
// Code adapted from http://compaspascal.blogspot.nl/2008/10/delphi-2009-strings-explained-by.html
var
UTF16Str : string;
UTF8Str : utf8string;
DanishStr: TDanishString;
L : Integer;
begin
{ TODO -oJan -cShouldHave : Test if Musica font is installed }
UTF16Str:=#$1D160;
MmoCharacter.Text := UTF16Str;
L := length(UTF16Str);
Assert (L=2);
Log('Assigned: UTF16Str := #$1D160');
Log(' This is a musical note (000011101000101100000),');
log(' see http://unicode.org/charts/PDF/U1D100.pdf');
Log('Length(UTF16Str)=2');
Log(' This character occupies 2 positions in UTF-16');
Assert (UTF16Str[1]=#$D834); // 110110 0000110100 First half of the symbol
Assert (UTF16Str[2]=#$DD60); // 110111 0101100000 Second half of the symbol
Log('UTF16Str[1]=#$D834');
Log('UTF16Str[2]=#$DD60');
UTF8Str := utf8string(UTF16Str);
MmoCharacter.Lines.Add(String(UTF8Str));
Log('');
Log('Assigned: UTF8Str := UTF16Str');
Log(' This is the second line (char) in the left memo');
L := Length(UTF8Str);
Assert (L=4);
Log('Length(UTF8Str)=4');
Log(' This character occupies 4 positions in UTF-8, each 1 byte');
Assert (UTF8Str[1]=#$F0); // 11110 000
Assert (UTF8Str[2]=#$9D); // 10 011101
Assert (UTF8Str[3]=#$85); // 10 000101
Assert (UTF8Str[4]=#$A0); // 10 100000
DanishStr:=UTF16Str;
Assert (DanishStr='??'); // Note how Windows incorrectly converts to two letters!
Assert (length(DanishStr)=2);
DanishStr:=UTF8Str;
Assert (DanishStr='??'); // Note how Windows incorrectly converts to two letters!
Assert (length(DanishStr)=2);
end;
procedure TFrmSurrogatePairs.Log(S: String);
begin
Mmo.Lines.Add(S);
end;
end.
和DFM:
object FrmSurrogatePairs: TFrmSurrogatePairs
Left = 0
Top = 0
Caption = 'Surrogate pairs'
ClientHeight = 273
ClientWidth = 600
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object MmoCharacter: TMemo
AlignWithMargins = True
Left = 3
Top = 3
Width = 134
Height = 267
Align = alLeft
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -107
Font.Name = 'Musica'
Font.Style = []
ParentFont = False
ReadOnly = True
TabOrder = 0
end
object Mmo: TMemo
AlignWithMargins = True
Left = 143
Top = 3
Width = 454
Height = 267
Align = alClient
Lines.Strings = (
'')
ReadOnly = True
TabOrder = 1
end
end
答案 1 :(得分:0)
Ok)??
表示UTF-8数据已正确解码为UTF-16,但UTF-16数据已转换为不支持这些Unicode字符的Ansi代码页。
Ок)рџ’‹рџ’‹
表示原始8位UTF-8八位字节按原样存储,扩展为16位值,而不是从UTF-8解码为UTF-16。