將項目從delphi7升級到DelphiXE(delphi2011) |
|
pcboy
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:177 回覆:1838 積分:1463 註冊:2004-01-13 發送簡訊給我 |
google翻譯並整理(俄文看不懂,整理只能按自己理解了,有錯誤希望大家糾正) 之前,DelphiXE的項目遷移問題的講的很少,不僅需要瞭解Unicode的,還需要一些其他的關注。在以下文章有很好的描述: 第1部分 (Delphi的Unicode世界第一部分:什麼是Unicode,你為什麼需要它,以及如何在Delphi中使用它 第一樓) 第2部分 (Delphi的Unicode世界第二部分:新的RTL特點和類來支持Unicode 第二樓) 第3部分 (Delphi的Unicode世界第三部分:修改你的代碼 第3樓) 在過去的一年,遷移項目到Delphi XE獲得了成功,並總結了量的經驗: 然而,有些其他性質的問題或,不是這方面的。 現在,沒有了這種「非技術」的問題。你得到一個Delphi XE的同時將獲得所有Delphi2010,Delphi2009,Delphi2007和Delphi 7的授權,這樣就能包容早期版本。 現在您可以執行順利遷移:「舊」項目(即那些不再要求發展,但前提是有用的),繼續在Delphi 7運行,並在適當的時候轉移到DelphiXE的最新版本。 如何得到以前的Delphi版本: 1)創建一個在Embarcadero的開發者網絡帳戶,如果它尚不存在。購買新產品時一般會註冊; 2)註冊一個新的產品(不是拿到key,過去是不可能的); 3)按照該鏈接並得到key: http://www.embarcadero.com/xe-earlier-versions ; 請注意,以前的版本可以在從購買之日起180天內,此優惠購買時獲得有效的「象徵性」(個人)牌照。 發表於DelphiXE的弗塞沃洛德列昂諾夫9月27日,2010 part1 google翻譯並整理 Delphi的Unicode世界第一部分:什麼是Unicode,你為什麼需要它,以及如何在Delphi中使用它 上傳者:Aleg Azarousky 摘要:本文討論了什麼是Unicode,Delphi使用unicode有什麼好處,以及如何使用2009年推出Delphi 中包含的Unicode 簡介 互聯網已經摧毀了有可能阻礙在世界各地分發軟件的地理障礙。因此,程序可以不再基於純粹的ANSI。世界採納以文字和數據傳輸標準的 Unicode(Unicode)。這可以讓你輸入一個在世界上的書面語言和使用任何虛擬的Unicode支持是現在 - 是在全球技術生態系統的規範。 什麼是Unicode? Unicode是一種編碼方案,支持幾乎所有文字都是一個字符集編碼。 Unicode 允許計算機支持幾乎任何語言,它的發展下的Unicode協會(Unicode協會)控制在一個特殊的標準錄製的書面文本。簡言之,Unicode是 一個系統,允許任何人使用你喜歡的字母表。例如,是一個克林貢(星際迷航中的某外星人種)的Unicode版本。 在此之前的文章,你不應該給你的目標是Unicode是什麼以及它如何工作,在這裡你將瞭解如何開始使用Delphi 2009的Unicode的全部信息。如果您需要有關 Unicode好故事,我們建議您閱讀這篇優秀的文章「絕對最低,必須知道每一個的字符集Unicode的軟件開發人員」(下稱「絕對最低每一個軟件開發的,積極的要關於Unicode和字符集知道(不!借口)「。,斯波斯基寫成由Joel喬爾正確指出的:」這並不難「這篇文章,我的第三部分,將談談 Unicode是如此重要的原因,以及如何Delphi將推出一種新類型的UnicodeString。。 為什麼我需要的Unicode? Delphi2009 在眾多的創新中最主要的是Unicode,它貫穿於整個產品的運行。在Delphi中普通的字符串(字符串)現在是一個Unicode字符串(基於 Unicode的字符串)。Delphi的一切都是與此相關的,它是IDE,編譯器的RTL和VCL,完全支持Unicode。 Delphi 過渡到Unicode - 自然。 Windows本身是完全基於Unicode的系統,所以這是很自然的為它編寫的應用程序,默認情況下應該使用 Unicode字符串。對於Delphi開發者不僅受益於事實,即它們現在可以使用和Windows相同的數據類型,。 Unicode 支持揭示了Delphi開發者的新的可能性:他們現在可以用Unicode讀,寫,接收,發送,顯示任何數據 - 任何事情都可以用Delphi構造。不用改變多少代碼,你可以準備你的應用程序的任何數據,您,您的客戶或用戶操作。以前的應用程序只能工作在ANSI記錄數據,可以很容易地修改,以與幾乎世界上任何字符集。 Delphi開發人員,即使他們不用做任何事情,現在都可以進入世界市場,以本地化開發然後翻譯成幾種語言。 Windows本身有許多不同的本地化版本,在Delphi編寫的應用程序,應該能與不同的語言所支持的Windows相適應,包括任何日文,中文,希臘文或俄文。您的程序的用戶可能無法進入的ANSI文本或不使用ANSI路徑名稱。基於ANSI的應用程序,在這種情況下並不總是就像希望那樣工作。基於Windows的應用程序在Delphi中創建完整的Unicode支持,在這種情況下,將正常工作。即使你不面對所有語言環境,告訴最終用戶他們仍然能正常工作,無論何種語言。 對於現有的ANSI - Delphi中創建的應用程序,本土化的優勢,進入世界市場(使用 Unicode)可能非常大。如果你要本地化的應用程序,Delphi可以很容易做到正確的應用過程中(設計時)的創建它。包的IDE直接讓你翻譯,編譯和部署從開發環境(IDE)的應用程序。如果您需要外部資金的轉移,開發環境可以導出一個譯員可以用便攜式外部經理轉換(外部翻譯經理)使用的形式您的項目。這些工具與Delphi中,和C Builder的,這使得您的應用程序簡單方便的本地化。 世界上使用Unicode,現在開發商和Delphi,很容易成為一個不可分割的組成部分。所以,如果你希望有機會與工作在Unicode數據,或者如果你想打開你的應用程序開發和全球市場的方式,Delphi 2009可以幫你做到這一點用。 一點術語 Unicode 是基於一個新的詞彙。例如,在「字符»(字符)的Unicode的概念並沒有準確地反映你的習慣來理解它。 Unicode是一種更準確的術語「代碼點» (代碼點)。在Delphi 2009,調用一下SizeOf(炭)將返回2,但是這並不是唯一的功能。在某些情況下,根據編碼,符號,可能需要兩年以上的字節。此類字符的序列被稱為「代理項對。」因此,「代碼點」 - 一個獨特的代碼分配到Unicode協會指定的元素。大多數情況下它是作為「符號」,但並不總是一樣的。 另一個術語,是指為Unicode,它是「物料清單」或字節順序標記。這是一個很短的前綴,在該文本文件的開頭插入來形容該文件中使用的編碼。 MSDN上有什麼一個BOM偉大的文章。一類新的TEncoding(將在第二部分所述)有一個方法 GetPreamble,對於給定的BOM編碼的回報。 這是所有需要解釋,但現在讓我們來看看如何使用Unicode字符串Delphi 2009的作品。 一種新型的UnicodeString Delphi2009 年默認字符串類型,是一種新型的UnicodeString。默認情況下,類似的UnicodeString為UTF - 16,在Windows中使用的相同。這是不同於以往的版本,它使用默認的類型AnsiString類型。在Delphi的RTL同期處理Unicode數據使用類型 WideString類型,而不是AnsiString類型,不計算在內的鏈接(而不是引用計數)的數量,因此不能被作為一個Delphi型「的默認字符串開發商看到。 Delphi2009年新的UnicodeString類型是設計了這樣一種方式相結合的優勢和AnsiString類型,和WideString。的UnicodeString可以包含Unicode字符,以及單字節的ANSI字符。 (請記住,您仍然可以使用 AnsiString類型和WideString)。 CHAR和PChar類型的類型現在分別代表和WideChar 和PWideChar。請注意,沒有一種類型的並沒有消失,所有類型,這是由開發人員使用繼續存在和運作,和以前一樣。 因此,在Delphi2009的原始字符串(string)將等同的UnicodeString,正常字符(char) - 現在WideChar,一個指針(PChar類型) - 現在是PWideChar。 也就是說,編譯器給出下面的代碼: type string = UnicodeString; Char = WideChar; PChar = PWideChar; UnicodeString可以指定任何其他類型的字符串值,AnsiString類型之間的分配和的UnicodeString會導致相應的轉換。因此,分配一個Unicode串的ANSI -行數據將會丟失如果Unicode字符串包含單字節的數據,因為這種類型的字符串 AnsiString類型轉換發生的損失不是單字節的數據。 重要的是要明白的UnicodeString了所有的其他字符串類型所享有的優勢(當然,除了優勢明顯的機會包含Unicode格式的數據)。您仍然可以附加任何字符串數據,參考他們的元素的索引,就可以與他們的符號「 」等 例如,一個字符的Unicode字符串可以通過索引訪問。考慮下面的代碼: var MyChar: Char; MyString: string; begin MyString := 『This is a string』; MyChar := MyString[1]; end; MyChar變量將包含從第一的位置,即「T」型性格。這段代碼執行的操作是不變的。倘若我們與Unicode數據的工作: var MyChar: Char; MyString: string; begin MyString := 『世界您好『; MyChar := MyString[1]; end; MyChar變量將包含從第一個位置,即「世」字。 勞動教養有一個隱藏的代碼頁轉換和元素大小的其他功能。如果用戶使用的移動到一個字符數組,它可能沒有擔心的元素的大小。 正如你可能已經猜到,這種新型串導致在現有的代碼更改。一個字符(char)的已不再是一個字節。事實上,一個字甚至不總是一個雙字節!因此,你可能要改變一些現有的代碼。我們一直在努力使盡可能簡單的過渡到新版本,並有信心,你現在可以實現非常快。在第二和第三部分,根據有關的新類型的 UnicodeString將繼續本文,您將瞭解新的Unicode特性RTL和編寫程序,您可能需要使用你的代碼中的具體方法。這篇文章將幫助你轉換為 Unicode,容易和輕鬆。 結論 除了Unicode字符串的事實,現在由默認字符串,Delphi現在能夠接收,處理和顯示,在世界上任何腳本或代碼頁。你的應用程序在Delphi 2009創建將可以輕易地與Unicode文字工作,幾乎所有的Windows支持的語言。用Delphi開發人員,現在可以輕鬆地找到並移動到另一種語言中的應用,以達到市場中,他們曾經是能去工作。居住在世界各地的Unicode,現在你的Delphi應用程序可以住在這兒。 在第二部分我們會考慮的Delphi運行時庫,這將允許您方便地使用Unicode字符串的變化。 google翻譯並整理 在在Unicode世界第二部分[全部]Delphi:新的RTL特點和類來支持Unicode 上傳者:弗拉基米爾Panarin 摘要:本文介紹的新功能提布隆運行時庫,這將有助於在使用Unicode字符串的工作。 簡介 在第一部分中,我談到了如何利於Delphi開發者對Unicode的支持,因為它允許您使用任何字符在Unicode宇宙套。我們已經回顧了新的UnicodeString類型和使用它在Delphi中的基本技術。 在第二部分我們來看看運行時庫的Delphi引入一些新功能支持Unicode,和一般技術處理字符串。 TCharacter類 蒂布龍的RTL包括一個新的類TCharacter,模塊中的字符描述。這是一個完全由私人類靜態函數組成。開發人員並不需要實例TCharacter,相反,最好只調用它的靜態方法。這個類是各種職務,包括: 字符轉換為大寫或小寫 確定什麼樣的性格類型屬,也就是說,這個數字是字母,標點符號,或別的東西。 TCharacter使用由Unicode協會規定的標準。 開發人員可以使用類TCharacter,執行許多上以前完成的一組符號(字符集的)不同的動作。例如,下面的代碼: uses Character; begin if MyChar in [『a』...』z』, 『A』...』Z』] then begin ... end; end; 可以很容易地被替換如下: uses Character; begin if TCharacter.IsLetter(MyChar) then begin ... end; end; 字符單元也包含了該履行TCharacter類似的功能相同的動作不同的功能數量。因此,如果你喜歡簡單地調用上面可以寫一寫如下功能: uses Character; begin if IsLetter(MyChar) then begin ... end; end; 因此,TCharacter類可用於執行大多數操作或測試,你可能需要。 此外,為確定是否TCharacter一個字符上限或下限的代理對部分方法。 類TEncoding Tiburon的RTL的還包括一個新的類TEncoding。它的目的 - 要求特定類型的編碼,所以你可以告訴VCL的,什麼類型的編碼在您的特定情況下使用。 例如,你有一個TStringList的實例,包含文字,你要寫入一個文件。以前,你可以這樣寫: 開始 ... MyStringList.SaveToFile('SomeFilename.txt'); ... 結束; 和文本將被寫入到一個在ANSI編碼的文件默認情況下使用。此代碼仍然可以正常工作 - 它寫在文件中的文本,使用,像以前一樣,美標ANSI編碼,但現在,Delphi支持Unicode字符串,開發人員可能需要編寫任何特殊編碼的字符串數據。因此,SaveToFile(如LoadFromFile)現在有一個可選的第二個參數指定編碼你想要的: begin ... MyStringList.SaveToFile(『SomeFilename.txt』, TEncoding.Unicode); ... end; 運行此代碼,該文件將被寫在Unicode(UTF - 16中)。 TEncoding也可以轉換從一個編碼的字節設置為另一個,以獲取有關字節和/或在一個字符串或字符數組字符的信息轉換成字節數組(數組的字節(Tbytes的))等等,這取決於字符串的編碼或任何字符串字符數組。 TEncoding類包含以下屬性,這給接觸到不同的編碼: class property ASCII: TEncoding read GetASCII; class property BigEndianUnicode: TEncoding read GetBigEndianUnicode; class property Default: TEncoding read GetDefault; class property Unicode: TEncoding read GetUnicode; class property UTF7: TEncoding read GetUTF7; class property UTF8: TEncoding read GetUTF8; 默認屬性是指為ANSI活躍的代碼頁。 Unicode的屬性是指為UTF - 16。 TEncoding還包括一個功能 class function TEncoding.GetEncoding(CodePage: Integer): TEncoding; 返回一個TEncoding,代碼頁發送到參數的實例。 此外,它具有以下功能: function GetPreamble: TBytes; 它返回一個給定的編碼的BOM。 TEncoding也與接口兼容。NET的類編碼。 TStringBuilder 在RTL現在有一類TStringBuilder。其目的是從標題明確 - 是一個類來構建(建立)線。 TStringBuilder包含一個重載函數的添加,替換和插入連續元素。這個類可以很簡單地創建許多不同類型的線路。在每個追加,插入和替換返回複製 TStringBuilder,這樣他們就可以很容易地結合起來,建立一個單一的線。 例如,你可以用它代替複雜的TStringBuilder格式。例如,你可以寫下面的代碼: procedure TForm86.Button2Click(Sender: TObject); var MyStringBuilder: TStringBuilder; Price: double; begin MyStringBuilder := TStringBuilder.Create(''); try Price := 1.49; Label1.Caption := MyStringBuilder.Append('The apples are $').Append(Price). AAppend(' a pound.').ToString; finally MyStringBuilder.Free; end; end; TStringBuilder也與接口兼容。NET的類的StringBuilder。 公佈新的字符串類型 Tiburon'a編譯器允許你聲明與選定的代碼頁相關聯行自己的類型。在這種情況下,任何可用的代碼頁號(MSDN上是一個優秀的可用頁面描述)。例如,如果你需要一個字符串類型,與ANSI -西裡爾相關,聲明: type // ANSI- - 1251 CyrillicString = type AnsiString(1251); 在這種情況下,一個新的字符串類型與西裡爾代碼頁相關的字符串。 額外的支持Unicode的RTL 在RTL例程,增加了支持Unicode字符串的數量。 StringElementSize StringElementSize返回該字符串元素(「代碼點」)的大小。考慮下面的代碼: procedure TForm88.Button3Click(Sender: TObject); var A: AnsiString; U: UnicodeString; begin A := 'This is an AnsiString'; Memo1.Lines.Add('The ElementSize for an AnsiString is: ' IntToStr(StringElementSize(A))); U := 'This is a UnicodeString'; Memo1.Lines.Add('The ElementSize for an UnicodeString is: ' IntToStr(StringElementSize(U))); end; 在這段代碼的執行結果如下: The ElementSize for an AnsiString is: 1 The ElementSize for an UnicodeString is: 2 StringCodePage StringCodePage類型的Word,該字符串返回值適當的代碼頁。 考慮下面的代碼: procedure TForm88.Button2Click(Sender: TObject); type // The code page for ANSI-Cyrillic is 1251 CyrillicString = type AnsiString(1251); var A: AnsiString; U: UnicodeString; U8: UTF8String; C: CyrillicString; begin A := 'This is an AnsiString'; Memo1.Lines.Add('AnsiString Codepage: ' IntToStr(StringCodePage(A))); U := 'This is a UnicodeString'; Memo1.Lines.Add('UnicodeString Codepage: ' IntToStr(StringCodePage(U))); U8 := 'This is a UTF8string'; Memo1.Lines.Add('UTF8string Codepage: ' IntToStr(StringCodePage(U8))); C := 'This is a CyrillicString'; Memo1.Lines.Add('CyrillicString Codepage: ' IntToStr(StringCodePage(C))); end; 在這段代碼的執行結果如下: The Codepage for an AnsiString is: 1252 The Codepage for an UnicodeString is: 1200 The Codepage for an UTF8string is: 65001 The Codepage for an CyrillicString is: 1251 有幾個程序來從一個代碼頁轉換到另一個字符串。它們是: UnicodeStringToUCS4String UCS4StringToUnicodeString UnicodeToUtf8 Utf8ToUnicode 此外,在RTL型介紹RawByteString,這是一個不與任何字符集關聯的字符串: RawByteString = type AnsiString($FFFF); 任用方式RawByteString - 讓每一個可能存在的代碼頁的字符串數據的傳輸,無需任何編碼轉換。這對於程序的編碼不喜歡搜索字符串的字節的問題,非常有用。這意味著,這些例程的參數的類型必須為RawByteString。 RawByteString類型變量需要使用盡可能少,因為這會導致數據丟失。讓我們來看看為什麼。 通常,字符串類型支持的任務。 例如: MyUnicodeString := MyAnsiString; 將如預期般運作 - 的內容將被放置在AnsiString類型的UnicodeString。作為一個規則,你可以指定一個行的另一種類型的字符串類型,編譯器做所有的工作轉變,如果可能的話。 然而,有些變化可能導致數據丟失,這應該是一個字符串時,會考慮分配具有Unicode的,字符串類型,不能包含Unicode數據類型。例如,你可以分配一個UnicodeString類型的變量AnsiString類型,但如果的UnicodeString包含不通過積極的ANSI,所包括的字符,這些字符轉換時將會丟失。考慮下面的代碼: procedure TForm88.Button4Click(Sender: TObject); var U: UnicodeString; A: AnsiString; begin U := 'This is a UnicodeString'; A := U; Memo1.Lines.Add(A); U := ' 2009!!'; A := U; Memo1.Lines.Add(A); end; 如果操作系統是活動代碼頁1252運行此代碼後,顯示如下: This is a UnicodeString ????? ?????????? ? ??? ??????? ? ?????????????? ?????? 2009!! 正如您可以看到從該西裡爾字符不是在Windows - 1252包括事實上,信息丟失,當您指定的UnicodeString AnsiString類型線。其結果是不可理解的文字的UnicodeString包含字符代碼頁中沒有表示的以AnsiString類型,所以這些字符流失,用問號代替。 SetCodePage SetCodePage,聲明在模塊System.pas procedure SetCodePage(var S: AnsiString; CodePage: Word; Convert: Boolean); 是一項新功能的RTL,定義為的是ANSI -行新的代碼頁。轉換一個可選的參數指定是否轉換為字符串傳遞給指定的代碼頁。如果轉換= False,則該行只是改變代碼頁。如果轉換= True,則傳遞的字符串將被轉換為代碼頁。 SetCodePage應謹慎使用,並十分謹慎。請記住,如果代碼頁不適合在現有的行(即轉換= false),則結果可以得到怪異。此外,如果在一個行中的數據轉化和新的代碼頁不能顯示原始字符,可能會導致數據丟失。 獲取行Tbytes的 勞動教養也包含字符串的字節數組幾個重載例程。正如你將看到在第三部分,用更好的代替了(字符串)通常的字符串數據緩衝區Tbytes的。可以很容易地做到這一點的RTL使用不同的重載版本BytesOf(),它需要一個不同類型的字符串。 結論 運行時庫Tiburon'a現在完全支持新的Unicode字符串 - 的UnicodeString。它包含訪問一個Unicode字符串,數據處理和轉換,管理代碼的網頁,並提供一個簡單的從舊版本過渡的新的類和例程。 Delphi的Unicode世界第三部分:修改你的代碼 上傳者:弗拉基米爾Panarin 摘要:本文討論了升級你的代碼到Delphi2009你需要做工作。 在本系列的第一部有人說,Delphi2009將默認UTF - 16為基礎的字符串。因此,現有代碼的某些部分可能需要修改。基本上,現有的大多數代 碼將正常工作在Delphi2009上。正如你將看到代碼中的重大變化只適用於非常具體的,甚至是深奧的時刻。不管是什麼,有必要考慮這些代碼 很可能在改特殊件下不得不修。還需要檢查這些代碼的結果,以確保UnicodeString正確的工作。 例如,用字符串的任何代碼,並與他們進行運算工作的指針應檢查與Unicode兼容。具體地說,這種代碼: 相信一下SizeOf(字符)= 1; 假設該字符串的長度等於每行的字節數; 誰寫和讀取任何永久的存儲線路,或使用作為數據緩衝區的字符串 應當進行審查,以確保這些功能並不影響工作。該代碼寫入和讀取從持久性存儲,應驗證的讀或寫一個字節為正確的字節數已經不再是一個單 一的字符。 作為一般規則,在代碼的任何變化都相當簡單,可以用最小的努力取得。 部分,應「的工作就是這樣」 它側重於那些部分代碼,這將繼續工作,不需要任何更改與新的UnicodeString正常。 VCL和勞動教養已經完全更新,以與Delphi2009年,總 是如此。小小的保留,是這樣的。例如,TStringList現在完全支持Unicode和所有現有的代碼,使用TStringList,應該像以前一樣。此外,T StringList已得到增強,工作的具體使用Unicode,所以如果你想使用新功能,你可以做到這一點,但是如果你不需要 - 你可以做一點也不覺 得。 正常使用String類型 基本上,代碼,使用string類型將像以前一樣起作用。沒有任何陰影類型需要字符串變量AnsiString類型,除以下所述。廣告行應改為AnsiSt ring類型字符串在所有的地方作為對數據緩衝區使用的地方。 運行時庫 添加到運行時庫中詳細討論了第二部分。 在這篇文章中沒有提到新的模塊添加到了RTL - AnsiString.pas。此模塊存在落後的代碼,使用或要求其工作AnsiString類型的兼容性。 代碼運行時庫運行如常,一般不需要改變。部分需要修改說明如下。 VCL的 所有的VCL支持Unicode。所有現有的VCL -組件進行安裝工作,因為他們總是被。幾乎所有的代碼,使用VCL的,一切都會正常工作。我們做了 偉大的工作,以確保VCL的兼容遺留代碼和Unicode。正常的VCL代碼不執行任何特定的字符串操作會如前。 線條的指數化 線條的指數化工程以同樣的方式和以前一樣,所以代碼的行的索引不需要改變的元素: var S: string; C: Char; begin S := 『This is a string』; C := S[1]; // C將包含的'T',但C,當然,WideChar end; 長/複製/刪除/一下SizeOf的字符串 複製功能將一如既往,沒有任何變化。這同樣適用於刪除並與SysUtils單元的字符串,工作的所有其他程序。 調用長度(SomeString),一如既往,返回傳遞的字符串元素的數量。 要求每行一下SizeOf標識符將返回,因為所有的字符串聲明4, - 這是一個連和指針大小為4。 挑戰的任何線路長度返回在該行的元素數。 考慮下面的代碼: var S: string; begin S:= 'abcdefghijklmnopqrstuvwxyz'; WriteLn('Length = ', Length(S)); WriteLn('SizeOf = ', SizeOf(S)); WriteLn('TotalBytes = ', Length(S) * SizeOf(S[1])); ReadLn; end. 由於其實施結果將收到以下: 隱藏圖像 為PChar類型工作的指針 為PChar類型的指針與合作將像以前一樣運行。編譯器知道PChar類型的大小,所以像下面的代碼將如預期: 風var p: PChar; MyString: string; begin ... p := @MyString[1]; Inc(p); ... end; 此代碼將完全一樣在以前的Delphi版本,但是,當然,其他類型的數據:PChar類型現在PWideChar和MyString的 - 現在的UnicodeString。 ShortString短 ShortString短保持不變,無論是在功能,並宣佈它會像以前一樣工作。 廣告ShortString短分配一個指定數量的AnsiChar'ov緩衝區。此代碼: var S: string[26]; begin S:= 'abcdefghijklmnopqrstuvwxyz'; WriteLn('Length = ', Length(S)); WriteLn('SizeOf = ', SizeOf(S)); WriteLn('TotalBytes = ', Length(S) * SizeOf(S[1])); ReadLn; end. 顯示以下內容: 隱藏圖像 請注意,整體規模的字母 - 26,這表明該變量包含AnsiChar'y。 還要考慮下面的代碼: type TMyRecord = record String1: string[20]; String2: string[15]; end; 此記錄將設在內存中,然後以同樣的方式 - 它會記錄從兩個含有AnsiChar'y AnsiString'ov。如果您有包含ShortString'i,那麼上面的代碼 將像以前的工作記錄了錄製文件,以及任何讀或寫不需要任何改變。 但請記住,煤焦 - 現在WideChar,所以如果你使用的代碼,從文件中讀取這些記錄,然後做一些像這樣: var MyRec: TMyRecord; SomeChar: Char; begin // MyRec ... SomeChar := MyRec.String1[3]; ... end; 你必須記住,在String1 SomeChar轉[3] WideChar屬於ANSIChar。如果您需要此代碼工作和以前一樣,變化的聲明SomeChar: var MyRec: TMyRecord; SomeChar: AnsiChar; // AnsiChar ShortString begin // MyRec ... SomeChar := MyRec.String1[3]; ... end; 必須檢查部件 在這篇文章中描述了不同的構造,應在與Unicode兼容現有的代碼進行測試。由於現在是WideChar字符,在字符數組或字符串的字節大小的數 據可能不正確。下面是一些例子的代碼結構,必須進行檢查,以確保新類型的UnicodeString兼容性。 SaveToFile / LoadFromFile 挑戰SaveToFile和LoadFromFile可以歸因於文章(部分應該「的工作就是這樣),如果他們讀,寫,正如他們以前以前的一部分。但是,您可 能要使用新的重載版本,這些程序如果你決定使用Unicode數據。 例如,TStrings現在包括以下一組重載方法: procedure SaveToFile(const FileName: string); overload; virtual; procedure SaveToFile(const FileName: string; Encoding: TEncoding); overload; virtual; 第二種方法 - 一個新的重載需要一個作為參數,該參數指定數據將被記錄在文件的編碼。 (。在第二部分中,您可以閱讀的類型TEncoding 描述)如果您調用一個方法,字符串數據將被記錄在相同的方式通常那樣 - 為ANSI數據。正因為如此現有代碼將一如既往完全相同。 但是,如果您需要編寫的Unicode格式的文本,你需要調用方法的第二個版本,對應的參數傳遞值類型TEncoding。如果不這樣做,將被寫入該 行作為ANSI數據很可能導致信息丟失。 因此,在這種情況下,最好的方法 - 分析的挑戰和SaveToFile LoadFromFile,並加入到他們第二次選擇,來說明如何保存或加載數據。如果 你認為永遠不會添加或Unicode字符串,你可以放下一切保持原樣。 用Chr 現有代碼的轉換中的一個字符的整數可以使用Chr價值。這可能會導致以下錯誤: [DCC Error] PasParser.pas(169): E2010 Incompatible types: 'AnsiChar' and 'Char' 如果代碼使用染色體的功能,有其結果變量屬於ANSIChar,轉讓那麼這個錯誤可以很容易被取代位於染色體的類型屬於ANSIChar職能轉變淘汰 。 也就是說,下面的代碼: MyChar := chr(i); 可以更換: MyChar := AnsiChar(i); 字符集 也許最常見的成語,它可以為編譯器的問題是在集合符號。以前,當字符佔用一個字節,存放在集合符號並沒有創造任何困難。但是,現在宣 布為char WideChar,因此不能再在集合中。因此,如果你有這樣的代碼: procedure TDemoForm.Button1Click(Sender: TObject); var C: Char; begin C := Edit1.Text[1]; if C in ['a'..'z', 'A'..'Z'] then begin Label1.Caption := 'It is there'; end; end; 你編譯它,你會得到一個警告,看起來像這樣: [DCC Warning] Unit1.pas(40): W1050 WideChar reduced to byte char in set expressions. Consider using 'CharInSet' function in 'SysUtils' unit. 如果你願意,你可以將代碼的缺席 - 編譯器會「知道」你正在嘗試做的,並產生正確的代碼。不過,如果你想獲得這個警告了,就可以使用 新的CharInSet: if CharInSet(C, ['a'..'z', 'A'..'Z']) then begin Label1.Caption := 'It is there'; end; CharInSet函數返回一個布爾值,該代碼將編譯沒有編譯器警告。 作為緩衝區的字符串 經常當與數據線的工作被用作緩衝區。這樣做是因為它常常是簡單 - 對字符串的工作是簡單明瞭。但是,現有的代碼,這是否在大多數情況 下,將需要更多的調整對基於事實的字符串是現在的UnicodeString。 有幾種方法來處理代碼,它使用字符串作為數據緩衝區。首先 - 它只是作為一個緩衝聲明一個變量,而不是字符串AnsiString類型為。如果 在使用Char'y代碼字節緩衝區的工作 - 這些變量聲明為屬於ANSIChar。如果你選擇這條路線,所有的代碼將一如既往,但是你應該記住:所 有的變量,這樣的字符串緩衝區的工作必須是ANSI類型。 第二,更忠實的方式 - 是從一個字符串轉換成字節數組或Tbytes的您的緩衝區。類型Tbytes的是專門為這個目的,而以同樣的方式和以前一 樣,如果你使用類型的字符串。 呼叫一下SizeOf緩衝區 呼叫一下SizeOf使用字符數組必須被檢查的有效性。考慮下面的代碼: procedure TDemoForm.Button1Click(Sender: TObject); var var P: array[0..16] of Char; begin StrPCopy(P, 'This is a string'); Memo1.Lines.Add('Length of P is ' IntToStr(Length(P))); Memo1.Lines.Add('Size of P is ' IntToStr(SizeOf(P))); end; 這在Memo1這段代碼顯示: Length of P is 17 Size of P is 34 在此代碼,長度返回字符串中的字符數34在這種情況下,即每兩個字符字節(加上終端符號)和sizeof返回該數組使用的字節數。在以前版本 的Delphi代碼在兩種情況下會返回17。 使用FillChar 調用FillChar還需要查詢字符串和符號。考慮下面的代碼: var Count: Integer; Buffer: array[0..255] of Char; begin // /現有代碼 - 不正確的,因為該字符串=的UnicodeString Count := Length(Buffer); FillChar(Buffer, Count, 0); // 正確的Unicode - 任何權利的選項 Count := SizeOf(Buffer); // << - 設置緩衝區的大小以字節為單位 Count := Length(Buffer) * SizeOf(Char); // <<-- 設置緩衝區的大小以字節為單位 FillChar(Buffer, Count, 0); end; Length返回的字符的大小,但FillChar預計,將在數個字節。在這種情況下,而不是長度在使用sizeof(或應當由字符的大小長度乘以)。 此外,由於默認大小為2字符,FillChar填補了,而不是像以前字符的字節串。 var Buf: array[0..32] of Char; begin FillChar(Buf, Length(Buf), #9); end; 這將填補一元的,而不是09和○九○九美元碼字符數組。要獲得前一個結果,代碼必須改變: var Buf: array[0..32] of Char; begin .. StrPCopy(Buf, StringOfChar(#9, Length(Buf))); .. end; 使用字母符號 下面的代碼 if Edit1.Text[1] = #128 then 認識到歐元符號,最後提供真實的ANSI代碼頁,在大多數。不過,Delphi2009年,它將給假,因為#128 - 一歐元兌多數ANSI -頁的象徵,它 在Unicode - 控制字符。歐元符號的Unicode代碼#$ 20AC條。 當升級到Delphi 2009,開發人員必須更換所有的字符代碼#128#255在他們的文字值,則: if Edit1.Text[1] = '€' then 將作為在ANSI 128#相同,但功能正常(即確定歐元符號)在Delphi 2009(其中'€'的代碼#$ 20AC條) 使用移動 應檢討使用的功能與移動字符串或字符數組。考慮下面的代碼: var Count: Integer; Buf1, Buf2: array[0..255] of Char; begin // 現有代碼 - 不正確的,因為該字符串=的UnicodeString Count := Length(Buf1); Move(Buf1, Buf2, Count); // 正確的Unicode Count := SizeOf(Buf1); // <<-- 設置緩衝區的大小以字節為單位 Count := Length(Buf1) * SizeOf(Char); // <<-- 設置緩衝區的大小以字節為單位 Move(Buf1, Buf2, Count); end; Length返回的字符的大小,但移動預計將在數個字節。在這種情況下,而不是長度在使用sizeof(或應當由字符的大小長度乘以)。 方法讀/ ReadBuffer為TStream 調用TStream.Read / ReadBuffer也應該考慮如果字符串或字符數組。考慮下面的代碼: var S: string; L: Integer; Stream: TStream; Temp: AnsiString; begin // 現有代碼 - 不正確的,因為該字符串=的UnicodeString Stream.Read(L, SizeOf(Integer)); SetLength(S, L); Stream.Read(Pointer(S)^, L); // 正確的數據為Unicode Stream.Read(L, SizeOf(Integer)); SetLength(S, L); Stream.Read(Pointer(S)^, L * SizeOf(Char)); // <<-- 設置緩衝區的大小以字節為單位 // 正確的ANSI數據 Stream.Read(L, SizeOf(Integer)); SetLength(Temp, L); // <<-- 使用臨時AnsiString類型 Stream.Read(Pointer(Temp)^, L * SizeOf(AnsiChar)); // <<-- 設置緩衝區的大小以字節為單位 S := Temp; // <<--轉換為Unicode字符串 end; 註:取決於格式的數據讀取。看到了一個新的類TEncoding說明,上面提到,以獲得有關正確的文本流中的編碼信息。 寫/ WriteBuffer 由於在案件讀/ ReadBuffer,使用TStream.Write / WriteBuffer應該檢查字符串或字符數組。考慮下面的代碼: var S: string; Stream: TStream; Temp: AnsiString; begin // 現有代碼 - 不正確的,因為該字符串=的UnicodeString Stream.Write(Pointer(S)^, Length(S)); // 正確的數據為Unicode Stream.Write(Pointer(S)^, Length(S) * SizeOf(Char)); // <<-- 設置緩衝區的大小以字節為單位 // 正確的ANSI數據 Temp := S; // <<--使用臨時AnsiString類型 Stream.Write(Pointer(Temp)^, Length(Temp) * SizeOf(AnsiChar));// <<-- 設置緩衝區的大小以字節為單位 end; 註:取決於格式的數據讀取。看到了一個新的類TEncoding說明,上面提到,以獲得有關正確的文本流中的編碼信息。 LeadBytes 替換此代碼: if Str[I] in LeadBytes then 使用功能IsLeadChar: if IsLeadChar(Str[I]) then TMemoryStream的 在這種情況下,當寫入文本文件使用TMemoryStream的,重要的是,作為初始數據寫入文件的字節順序標記(BOM)。這裡有一個在BOM文件的 示例條目: var BOM: TBytes; begin ... BOM := TEncoding.UTF8.GetPreamble; Write(BOM[0], Length(BOM)); 整個編寫代碼應改為工作UTF8的編碼為Unicode字符串: 風險值 溫度:Utf8String; 開始 ... 溫度:= Utf8Encode(乙方); / / < - STR基因 - 字符串寫入到文件 寫(指針(臨時)^,長度(暫)); / /寫(指針(乙方)^,長度(乙方)); < - 這是原來的調用write寫一個字符串到一個文件 var Temp: Utf8String; begin ... Temp := Utf8Encode(Str); // <--STR基因 - 字符串寫入到文件 Write(Pointer(Temp)^, Length(Temp)); //Write(Pointer(Str)^, Length(Str)); <-- 這是原來的調用write寫一個字符串到一個文件 TStringStream TStringStream現在來自新類型TByteStream。 TByteStream增加了物業字節,使直達TStringStream的字節。 TStringStream繼續照常工作, 但它的字符串店,現在是一個Unicode字符串。 MultiByteToWideChar 挑戰MultiByteToWideChar可以簡單地拆卸和更換一個簡單的任務。使用MultiByteToWideChar的例子: procedure TWideCharStrList.AddString(const S: string); var Size, D: Integer; begin Size := SizeOf(S); D := (Size 1) * SizeOf(WideChar); FList[FUsed] := AllocMem(D); MultiByteToWideChar(0, 0, PChar(S), Size, FList[FUsed], D); Inc(FUsed); end; ,後過渡到Unicode,此代碼已被修改為編譯為ANSI和Unicode: procedure TWideCharStrList.AddString(const S: string); var L, D: Integer; begin FList[FUsed] := StrNew(PWideChar(S)); Inc(FUsed); end; SysUtils.AppendStr 這種方法只能使用AnsiString類型,而不是為的UnicodeString超載。 更換電話是這樣的: AppendStr(String1, String2); 此代碼: String1 := String1 String2; 或者,更好的是,使用一個新的類TStringBuilder來連接字符串。 GetProcAddress函數 當你調用GetProcAddress應該總是使用PAnsiChar(SDK中是沒有後綴「W」的功能)。例如: procedure CallLibraryProc(const LibraryName, ProcName: string); var Handle: THandle; RegisterProc: function: HResult stdcall; begin Handle := LoadOleControlLibrary(LibraryName, True); @RegisterProc := GetProcAddress(Handle, PAnsiChar(AnsiString(ProcName))); end; 註:Windows.pas包含一個重載方法,執行此轉換。 使用轉換為PChar類型(),工作的指針指向了不為字符類型 在以前的版本中,並非所有類型的指針算術支持。正因為如此,這類招牌上執行算術運算,他們轉換為PChar類型。在Delphi 2009年,可能包 括指針算術指令編譯器,它是專門為類型PByte包括在內。所以,如果你有類似的代碼轉換成一個指向PChar類型上執行算術運算: function TCustomVirtualStringTree.InternalData(Node: PVirtualNode): Pointer; begin if (Node = FRoot) or (Node = nil) then Result := nil else Result := PChar(Node) FInternalDataOffset; end; 您應該取代它而不是使用PByte PChar類型: function TCustomVirtualStringTree.InternalData(Node: PVirtualNode): Pointer; begin if (Node = FRoot) or (Node = nil) then Result := nil else Result := PByte(Node) FInternalDataOffset; end; 在上面的片斷節點不包含字符數據。他只轉換為PChar類型訪問數據,通過一個節點後的字節數指定。此前它曾擔任一下SizeOf(字符)=一 下SizeOf(字節)。現在,它不會工作。為了使代碼正常工作,你應該使用PByte代替PChar。如果你讓一切保持不變,結果將指向無效的數據 。 期權Variant數組 如果您的代碼使用TVarRec工作與參數 - 變量數組 - 你可能需要編輯它來工作的UnicodeString。要做到這一點,現在有一種新型的vtUnicodeString,數據存儲從一的UnicodeString。考慮下面 這段DesignIntf.pas,顯示,在這種情況下你應該增加新的代碼才能使用的UnicodeString。 procedure RegisterPropertiesInCategory(const CategoryName: string; const Filters: array of const); overload; var I: Integer; begin if Assigned(RegisterPropertyInCategoryProc) then for I := Low(Filters) to High(Filters) do with Filters[I] do case vType of vtPointer: RegisterPropertyInCategoryProc(CategoryName, nil, PTypeInfo(vPointer), ); vtClass: RegisterPropertyInCategoryProc(CategoryName, vClass, nil, ); vtAnsiString: RegisterPropertyInCategoryProc(CategoryName, nil, nil, string(vAnsiString)); vtUnicodeString: RegisterPropertyInCategoryProc(CategoryName, nil, nil, string(vUnicodeString)); else raise Exception.CreateResFmt(@sInvalidFilter, [I, vType]); end; end; CreateProcessW 的Unicode的CreateProcess(CreateProcessW)版本的作品有點不一樣的ANSI版本。從MSDN描述報價參數lpCommandLine: 「的Unicode此功能,CreateProcessW,版本可以改變這個字符串的內容因此,這個選項不能成為回憶,只有讀書(即是一個常數變量或字符 串)如果這個參數 - 。。一個常數函數可能會導致訪問錯誤。「 正因為如此現有代碼調用CreateProcess,可以開始提供訪問錯誤(訪問衝突)時,在德爾福2009年編製。 這樣的代碼例子: 轉移一個字符串常量 CreateProcess(nil, 'foo.exe', nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo); const cMyExe = 'foo.exe' begin CreateProcess(nil, cMyExe, nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo); end; ;與鏈接(引用計數)-1號輸電線路: const cMyExe = 'foo.exe' var sMyExe: string; begin sMyExe := cMyExe; CreateProcess(nil, PChar(sMyExe), nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo); end; 驗證碼 這裡是一個可能的地方在代碼中,你需要找到清單,檢查是否已準備好您的代碼正確使用Unicode: 找到任何「字符」使用「屬於ANSIChar」,或驗證工作緩衝區使用Unicode正確; 找到「字符串[」和驗證字符符號論(即WideChar)進入連結歡迎。 檢查出與AnsiString類型,ANSIChar和PAnsiChar隱工作,確保它仍然是必要的,正常工作; 發現隱式使用ShortString短,確保它仍然是必需的,是否工作正常; 找到電話通話時長(和檢查,沒有任何暗示的長度是因為這一下SizeOf相同; 找到挑戰複製(,尋求(,指針(,AllocMem(和GetMem函數(並檢查他們的工作與字符串或字符數組正確。 這是一個典型的設計,這可能改變以支持新的類型的UnicodeString。 結論 這是在代碼中要檢查的Unicode世界上所有生命的正確性潛在的瓶頸。你的代碼的大多數仍然是可行的。的警告,這將讓你從編譯器的大部分 代碼,你可以輕鬆解決。一個事物的檢查中很大一部分是相當罕見的,因此幾乎所有代碼會工作得很好。
------
能力不足,求助於人;有能力時,幫幫別人;如果您滿意答覆,請適時結案! 子曰:問有三種,不懂則問,雖懂有疑則問,雖懂而想知更多則問! |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |