久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

UnicodeinRADStudio

 quasiceo 2013-01-11
經(jīng)過黃叉叉的唆使,我也在家里裝上了Delphi2010,,一般情況下編譯問題不大,,但是好多從以前的工程轉(zhuǎn)過來的項目上就有些問題了,經(jīng)常性的問題就是Unicode的問題,!于是網(wǎng)絡Google一番,,在Delphi的官方站點上發(fā)現(xiàn)了Unicode的一些說明,于是大致的翻譯記錄一下,,原文地址:http://docwiki./RADStudio/en/Unicode_in_RAD_Studio
在RADStudio中,,基于ANSI-字符串改為基于Unicode字符串:現(xiàn)在的默認情況下,string類型是一個Unicode字符串(UnicodeString),。這個主題將會告訴你如何更好的去處理字符串,。
RADStudio現(xiàn)在完全支持Unicode標準,但是在您的某些涉及到字符串操作部分的代碼將會需要一些變動,,雖然已經(jīng)花了很多功夫以使用戶進行最低限度的變化,!這是新的數(shù)據(jù)類型的介紹,,現(xiàn)有的數(shù)據(jù)類型和功能仍和以往一樣。根據(jù)公司內(nèi)部的Unicode轉(zhuǎn)換的經(jīng)驗,,現(xiàn)有的開發(fā)應用程序應該比較順利遷移,。
現(xiàn)有的String類型
預先存在的數(shù)據(jù)類型AnsiStringWideString功能與以前一樣的方式。
注意:ShortString最多包含255個字符,,字符為單字節(jié)數(shù)據(jù),,且只有一個字符計數(shù),不包含編碼頁(codepage)信息,。對于特定應用,,ShortString可以包含UTF-8數(shù)據(jù),但缺乏普遍性,。
此前系統(tǒng)的string實質(zhì)上是代表AnsiString.下表是之前AnsiString各字段含義的內(nèi)存表示格式:
引用計數(shù)位置字符長度位置字符數(shù)據(jù)開始位置
控制符結(jié)尾
偏移-8偏移-4偏移0長度

在RADStudio中,AnsiString格式已經(jīng)發(fā)生改變,,新加入了兩個字段(fields),分別是“編碼頁”字段和“元素大小”字段(CodePageandElemSize),。從而使得AnsiString表示格式與新的UnicodeString類型完全兼容,。
WideString
WideString之前用于Unicode字符數(shù)據(jù)。其格式本質(zhì)上與WindowsBSTR完全一樣,。WideString仍舊適用于COM應用,。
新String類型:UnicodeString
在RADStudio中,新的默認string類型是UnicodeString類型,。
在Delphi中,,Char和Pchar類型分別為WideChar和PwideChar。
注意:2009之前的版本,,string代表AnsiString,,而Char和Pchar類型分別為AnsiChar和PansiChar,此一區(qū)別,,需要特別注意,。
在C++中,_TCHAR映射到一個可選的浮動興致的定義_TCHAR可以作為wchart_t也可以是Char
VCL中限制使用的是UnicodeString類型,,它不再是單字節(jié)或MBCS字符串的字符串值。
現(xiàn)在的UnicodeString的內(nèi)存存儲格式為:
代碼頁位置元素尺寸位置代碼頁位置長度位置字符數(shù)據(jù)開始位置NullTerm
-12-10-8-40長度*元素尺寸
UnicodeString可用下面的ObjectPascal結(jié)構(gòu)來表示:
UnicodeinRADStudio UnicodeinRADStudio 代碼typeStrRec=record
CodePage:Word;
ElemSize:Word;
refCount:Integer;
Len:Integer;
caseIntegerof
1:array[0..0]ofAnsiChar;
2:array[0..0]ofWideChar;
end;
UnicodeString加入了“編碼頁”和“元素大小”二字段來說明string內(nèi)容,。UnicodeString與所有其它string類型賦值兼容(isassignmentcompatiblewithallotherstringtypes),。但是,在AnsiString和UnicodeString之間的賦值仍然會出現(xiàn)“往上轉(zhuǎn)換”或“朝下轉(zhuǎn)換”(stilldotheappropriateupordownconversions),。應注意,,不建議將UnicodeString類型賦值給AnsiString類型,這可能導致數(shù)據(jù)丟失,。
還應注意AnsiString也包含了CodePage和ElemSize二字段,。
UnicodeString在UTF-16里邊,,有如下理由:
UTF-16與底層操作系統(tǒng)格式匹配。
UTF-16減少了顯式/隱式的轉(zhuǎn)換,。
調(diào)用WindowsAPI時的性能更高,。
操作系統(tǒng)不需與UTF-16作任何轉(zhuǎn)換。
基本多語言平臺(BMP)已包含了目前世界上絕大多數(shù)流行語言文字字形,,且適合于單個UTF-16字符(16bits),。
Unicode“替換對”(surrogatepairs)與多字節(jié)字符集(MBCS)類似,且更可預測,,也更標準,。
調(diào)度COM接口時,UnicodeString能夠提供與WideString之間的雙向轉(zhuǎn)換,。
UTF-16中的字符可以是2或4字節(jié),,因此,string中元素的數(shù)目不必一定等于其字符數(shù)目,。如果string中只包含BMP字符,,則字串中的字符個數(shù)和元素個數(shù)一定相等。
采用UnicodeString有如下好處:

  • 可以實現(xiàn)字串中的字符“引用計數(shù)”(Itisreference-counted),。
  • 可以解決以前應用中的遺留問題,。
  • 使得AnsiString支持編碼信息(codepage),從而消除了隱含類型轉(zhuǎn)換中潛在的數(shù)據(jù)丟失問題,。
  • 編譯器能夠確保數(shù)據(jù)在改變之前的正確性,。

WideString沒有引用計數(shù),因此UnicodeString在某些類型的應用中更加靈活、更加高效(WideString更合適COM),。
索引
UnicodeString類型的實例可以尋址字符,。尋址以1為基,如同AnsiString一樣,。參考下述代碼:
varC:Char;
S:
string;
begin
...
C:
=S[1];
...
end;
此種情況下,,編譯器必須確保S中的數(shù)據(jù)具有適當?shù)母袷健>幾g器產(chǎn)生代碼必須確保對字串元素的賦值具有合適的類型,,并通過調(diào)用UniqueString函數(shù),,保證實例的唯一性(即,以“1”為基的引用),。代碼中,,由于字串可能包含Unicode數(shù)據(jù),編譯器在尋址字符陣列之前還需調(diào)用UniqueString函數(shù),。
編譯器條件
在Delphi及C++Builder中,,可以使用條件編譯允許Unicode和非Unicode代碼兼容共存。
Delphi
{$IFDEFUNICODE}
C++Builder
#ifdef_DELPHI_STRING_UNICODE
變化摘要

  • String現(xiàn)在代表UnicodeString而不是AnsiString.
  • Char現(xiàn)在代表WideChar(2字節(jié)而非1字節(jié)),,且是UTF-16字符,。
  • Pchar現(xiàn)在表示PWideChar.
  • C++中,,System::String現(xiàn)在代表UnicodeString類。
未變化摘要

  • AnsiString.
  • WideString.
  • AnsiChar,PAnsiChar.
  • WideChar,PWideChar
  • 仍可使用隱含類型轉(zhuǎn)換,。
  • AnsiString使用用戶活動“編碼頁”,。
與字符大小無關(guān)的代碼結(jié)構(gòu)
下述操作與字符大小無關(guān):

  • 字符串串聯(lián):
+
+
+
Concat(,)

  • 標準string函數(shù)
  • 字符串運算:

CompareStr()
CompareText()等

  • FillChar()

    • FillChar(Rect,SizeOf(Rect),#0)
    • FillChar(WndClassEx,SizeOf(TWndClassEx),#0).注意到WndClassEx.cbSize:=SizeOf(TWndClassEx);

  • WindowsAPI

    • API調(diào)用默認為其WideString("W")版本。
    • PChar()類型轉(zhuǎn)換仍具有相同語義,。


代碼//GetModuleFileName例子:
functionModuleFileName(Handle:HMODULE):string;
varBuffer:array[0..MAX_PATH]ofChar;
begin
SetString(Result,Buffer,
GetModuleFileName(Handle,Buffer,Length(Buffer)));
end;
//GetWindowText例子:
functionWindowCaption(Handle:HWND):string;
begin
SetLength(Result,
1024);
SetLength(Result,
GetWindowText(Handle,PChar(Result),Length(Result)));
end;
//String字符索引舉例:
functionStripHotKeys(constS:string):string;
varI,J:Integer;
LastChar:Char;
begin
SetLength(Result,Length(S));
J:
=0;
LastChar:
=#0;
forI:=1toLength(S)do
begin
if(S[I]'&')or(LastChar='&')then
begin
Inc(J);
Result[J]:
=S[I];
end;
LastChar:
=S[I];
end;
SetLength(Result,J);
end;
與“字符大小”相關(guān)的代碼結(jié)構(gòu)
在些操作確實與字符大小相關(guān),。下面函數(shù)及特征列表中也包含了可能的“可移植”版本??梢来酥貙懽约旱拇a,,以便于移植,也就是使得你的代碼在AnsiString和UnicodeString變量中都能夠正常運行,。
SizeOf()–改用可移植指令Length().
Move(...CharCount)–改用可移植的Move(...CharCount*SizeOf(Char)).
StreamRead/Write--改用可移植的AnsiString,SizeOf(Char)或Tencoding類,。
FillChar(,,)--改用*SizeOf(Char)(填充#0時),或用StringOfChar函數(shù),。
GetProcAddress(,)–改用提供的重載函數(shù)并改為PWideChar.
使用類型轉(zhuǎn)換或Pchar作指針運算—在文件頂端加入{IFDEFPByte=PChar}(用Pchar作指針運算時時),。或用{POINTERMATH}編譯指令,,對所有的類型指針打開(即設為ON),,以便按照“元素大小”來增/減量(increment/decrement)。
字符集合結(jié)構(gòu)
可能需要修改的結(jié)構(gòu):

  • in--代碼生成正確(但>#255的字符不在集合當中).編譯器會提出警告:"WideCharreducedinsetoperations".根據(jù)你的代碼,,你可以安全地關(guān)閉警告,。或者,,你可使用函數(shù)CharinSet取而代之,。
  • inLeadBytes–這是全局性的LeadBytes集合,用于本地MBCSANSI.UTF-16仍保留了"leadchar"的概念(#$D800-#$DBFF為高替代,,#$DC00-#$DFFF為低替代),。想改變之,可使用重載IsLeadChar指令,。ANSI版會檢驗LeadBytes.而WideChar版本只在“高/低替代”(high/lowsurrogate)時作驗證,。
  • 字符分類—使用TCharacterstatic類。該字符單元提供了一些函數(shù)用于分類字符:IsDigit,IsLetter,IsLetterOrDigit,IsSymbol,IsWhiteSpace,IsSurrogatePair,等等,。這些都是基于直接來自Unicode.org的表數(shù)據(jù)的,。
當心這些結(jié)構(gòu)
特別注意下列有問題的代碼結(jié)構(gòu)
類型轉(zhuǎn)換將類型模糊化:
有疑問的類型轉(zhuǎn)換–產(chǎn)生警告:
直接構(gòu)造、操作或訪問字串內(nèi)部結(jié)構(gòu),。有些,比如AnsiString,,其內(nèi)部已經(jīng)變化,,因此是不安全的,。建議使用StringRefCount,StringCodePage,StringElementSize及其它函數(shù)來獲取字串信息。
運行時庫
重載.對函數(shù)PChar,,已有對應版本PAnsiChar和PWideChar,,建議使用適當函數(shù)。
SysUtils.AnsiXXXX函數(shù),,如AnsiCompareString:
AnsiStringsunit中的AnsiXXXX函數(shù)提供了SysUtils.AnsiXXXX函數(shù)相同的功能,,但其只適用于AnsiString.AnsiStrings.AnsiXXXX對AnsiString能夠給出比SysUtils.AnsiXXXX函數(shù)更好的性能,其原因是它們不進行隱含轉(zhuǎn)換操作,。而后者同時適用于AnsiString和UnicodeString,。
Write/Writeln和Read/Readln
繼續(xù)轉(zhuǎn)換到/從ANSI/OEM代碼頁。
控制臺是主要的ANSIorOEM
為以前的應用程序提供更好的兼容性,。
TFDD(文本文件設備驅(qū)動程序):
TTextRecTFileRec.
文件名是WideChar,但是同上所說,數(shù)據(jù)是ANSI/OEM.
PByte–用$POINTERMATHON聲明,。允許陣列尋址及指針運算,如同PAnsiChar.
字串信息函數(shù)Stringinformationfunctions:
StringElementSize返回實際數(shù)據(jù)的大小,。
StringCodePage返回的字符串數(shù)據(jù)的代碼頁,。
StringRefCount返回的引用計數(shù)。
RTL提供了幫助函數(shù),,可幫助在“編碼頁”和“元素大小”之間進行顯式的轉(zhuǎn)換,。通常開發(fā)人員在字符陣列上使用MOVE函數(shù)時,并不知道元素大小,。但若能確認所有的RValue引用都產(chǎn)生了對RTL的正確調(diào)用從而保證了合適的元素大小,,問題就得以緩解。
組件和類

  • TStrings:內(nèi)部保存有UnicodeString(仍需聲明為string).
  • TWideStrings(可能被棄用)未改變,。在內(nèi)部使用WideString(BSTR),。
  • TStringStream
已被重寫-默認為默認ANSI編碼的內(nèi)部存儲。
Encodingcanbeoverridden.
考慮使用TStringBuilder替代TStringStream去從bitsandpieces來構(gòu)造一個字符串

  • TEncoding
Defaultstousers’activecodepage.
支持UTF-8.
支持UTF-16,UTF-16be,UTF-16le
ByteOrderMark(BOM)support.
Youcancreatedescendentclassesforuser-specificencodings.(您可以繼承該類創(chuàng)建自己的特定編碼)

  • 組件流(即DFM文本文件)
完全向后兼容
StreamasUTF-8onlyifcomponenttype,propertyornamecontainsnon-ASCII-7characters.
Stringpropertyvaluesarestillstreamedin“#”escapedformat.
MayallowvaluesasUTF-8aswell(openissue).
OnlychangeinbinaryformatispotentialforUTF-8dataforcomponentname,properties,andtypename.
字節(jié)順序標志(ByteOrderMark)
就在文件中加入“字節(jié)順序標志”(BOM)以表示其編碼:

  • UTF-8使用EFBBBF.
  • UTF-16小端:使用FFFE.
  • UTF-16大端:使用FEFF.

StepstoUnicode-enableyourapplications
用戶需要進行如下步驟:

  • 檢查(所有)char-和string-相關(guān)函數(shù).
  • 重建應用.
  • 檢查替代符號對(Reviewsurrogatepairs).
  • 檢查string有效性/安全性(payloads).

新增Delphi編譯警告
NewwarningshavebeenaddedtotheDelphi編譯程序新增了類型轉(zhuǎn)換(如由UnicodeString或WideString朝下轉(zhuǎn)換成AnsiString或AnsiChar)相關(guān)的可能錯誤警告,。當將應用轉(zhuǎn)換到Unicode時,,應該使能警告1057和1058,以支持在代碼中發(fā)現(xiàn)問題區(qū)域,。

  • 1057隱含從'%s'到'%s'的類型轉(zhuǎn)換(IMPLICIT_STRING_CAST),,當編譯程序檢測到必須將AnsiString(或AnsiChar)隱式地轉(zhuǎn)換為某種Unicode(UnicodeString字串或WideString字串)形式時發(fā)出該警告。(注意:該警告最終將會被默認使能).
  • 1058從'%s'到'%s'隱含字串類型轉(zhuǎn)換可能有數(shù)據(jù)丟失,。(IMPLICIT_STRING_CAST_LOSS)當編譯程序檢測到必須將某種Unicode(UnicodeString字串或WideString字串)形式隱式地轉(zhuǎn)換為AnsiString(或AnsiChar)字串時發(fā)出該警告,。這是一種潛在的損失性轉(zhuǎn)換,這是因為有些字符,,無法在目標串的編碼頁中表示出來,。(注意:注意:該警告最終將會被默認使能).
  • 1059:略
  • 1060:略


  • 保持源文件為UTF-8格式.
  • 當代碼必須是AnsiString或AnsiChar時,在IDE中進行重構(gòu)(refactoring),。(代碼仍舊可移植codeisstillportable).
  • Static代碼檢查:
  • 留意所有警告(乃至錯誤):
  • 確認代碼意圖

建議
保存源文件中的UTF-8格式:
Delphi2005,2006,2007都支持.
文件仍然能夠以Ansi的形式編譯(可以使用codepage編譯器開關(guān)).
WriteaUTF-8BOMtosourcefile.Makesureyoursourcecontrolmanagementsystemsupportsthesefiles(mostdo).
PerformIDErefactoringwhencodemustbeAnsiStringorAnsiChar(codeisstillportable).
靜態(tài)代碼審查:

  • Iscodemerelypassingthedataalong?
  • Iscodedoingsimplecharacterindexing?
注意所有的警告(elevatetoerrors):

  • 可疑的指針類型轉(zhuǎn)換,。
  • 隱顯視轉(zhuǎn)換
明確代碼的目的

  • 代碼是否將字符串作為一個動態(tài)數(shù)組使用,,如果是,使用TBytes類型代替它
  • 一個Pchar能否被轉(zhuǎn)換成Pointer進行指針運算,?如果可以轉(zhuǎn)換成PByte類型,,替代它,同時打開編譯器開關(guān)$POINTERMATHON

    本站是提供個人知識管理的網(wǎng)絡存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多