delphi 2007以UTF-8字符串或任何其他方式显示unicode U + 1F48B

时间:2012-10-24 02:53:44

标签: delphi sqlite unicode utf-8

我有一个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管理器中的样子:

enter image description here

但无论我做什么(UTF8Decode和一些自定义转换)我都无法在我启用Unicode的TNTStringGrid中显示它。

是的,我可以得到OK)?显示,但然后去Ок)рџ'<џџ'<或这是它看起来像真实(UTF8Encoded):РћРє)рџ'<рџ'<< / p>

我知道这是一个难题,但必须有一个解决方案,因为SQLite管理器显示它绝对正确。

那么如何显示那些U +字符和普通文字?

请帮忙! 3个昼夜与这项任务作斗争。

2 个答案:

答案 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。