Delphi2009下开发注意事项

来源:互联网 发布:app加密软件 编辑:程序博客网 时间:2024/05/21 18:39

原创出自:http://hi.baidu.com/superkinger/blog/item/be2175589a9126d99d820474.html

 

 现有 Delphi 项目迁移到 Tiburon 中的注意事项


随着 Embarcadero 8 月 25 号发布 RAD Studio 2009 (Tiburon) 以来(Tiburon 的 RTM日期可能要延后到 9 - 10 月),随着 Tiburon 全面支持 Unicode,现有的 Delphi / C++ Builder项目要迁移到 Unicode 下应该注意些什么也成为大家最为关心的问题。Tiburon 对 Unicode 的支持不仅仅是将原来 类型映射为AnsiString 的 String 类型直接改成 WideString,而是对 AnsiString 结构作出修改,同时增加了UnicodeString 类型来完美支持 Unicode。这意味着,要想平稳迁移到 Unicode 下,程序员不得不对现有代码作出一定的修改。

在 Tiburon 以前的版本中,AnsiString 和 WideString 除了 data size 不同外,在功能上是相同的。早先版本的 AnsiString 的结构如下:

Format of AnsiString Data Type  


Ansistring结构

                                         Reference Count    Length    String Data (Byte sized)          Null Term 
                                          -8                           -4             0    Length  

 

Delphi2009默认的String 结构

CodePage   Element Size   Reference Count    Length    String Data (element sized)    Null Term 
-12             -10                  -8                            -4            0    Length * elementsize

 

 

而这个结构在 Tiburon 中已经发生变化,AnsiString 增加了两个新的 fields, 一个是 CodePage,一个是 ElemSize,这样做可以让新版的 AnsiString 和 UnicodeString 在结构上保持一致。

而 WideString 类型在早先的版本中用来保存双字节数据。其本质和 Windows BSTR 是一样的。在 Tiburon 中WideString 仍然是为 COM 保持兼容的,也就是说它依然没有引用计数,相比较而言,UnicodeString 在性能和效率上将会是COM 以外的程序首选的字符类型。

闪亮登场的 UnicodeString 类型

Tiburon 中,新的、默认的 string 就是 UnicodeString。这个类型既可以包含 ANSI 字符,也可以包含 Unicode 字符。下面是 UnicodeString 类型的结构:

Format of UnicodeString Data Type  

CodePage   Element Size   Reference Count    Length    String Data (element sized)    Null Term  
-12              -10                  -8                           -4            0    Length * elementsize   


UnicodeString 和 AnsiString 都是如上的结构,尽管 UnicodeString 包含是双字节数据,AnsiString 包含的是单字节的。

用 Object Pascal 语言来描述 UnicodeString 的结构,应该是这样:

type
StrRec = record
    CodePage: Word;
    ElemSize: Word;
    refCount: Integer;
    Len: Integer;
    case Integer of
      1: array[0..0] of AnsiChar;
      2: array[0..0] of WideChar;
end;

UnicodeString 增加了 code page 字段和 element size 来描述字符串内容,这使得 UnicodeString和其它类型的字符串可以很好的相兼容,所以 AnsiString 和 UnicodeString 可以很方便的互相转换,唯一要注意的是,当把UnicodeString 向下转型到 AnsiString 的时候,可能会丢失数据,因此强烈建议你不要这么做。UnicodeString保存的是 UTF-16 字符。

在旧的环境下,可以使用编译标志 Unicode 来判断编译环境是否支持 UnicodeString,以便您可以在同一套代码中维护不同版本的字符支持环境。编译指令如下:

Delphi 使用:
     {$IFDEF Unicode}
C++ Builder 使用:
     #ifdef _DELPHI_STRING_UNICODE

变化概要:

String 类型映射为 UnicodeString 而不是 AnsiString
Char 类型映射为 WideChar(2 bytes not 1 byte), 并且是 UTF-16 字符
PChar 类型映射为 PWideChar
C++ 中,System::String 映射到 UnicodeString 类
Delphi 中,AnsiString 映射为早先版本中默认的 string
未变化概要:

AnsiString
WideString
AnsiChar
PAnsiChar
隐式转换仍然可用
用户的活动页代码(The user's active code page)控制着模式(ANSI vs. Unicode),所以 AnsiString 仍然可以支持
由于这些变化,代码编写上也出现了一些值得注意的情况,特别是在你打算将旧有的项目迁移到 Tiburon 下时更是如此。下面就列出一些发生的变化情况以及编写代码时应该注意的注意事项。

下面的操作将不再依赖字符 Size:

合并字符串  
+
Concat( , )
标准字符串函数

Length()返回字符元素的长度,此值可能和字符在字节长度上并不匹配。SizeOf 函数则返回数据的字节长度,这意味着 SizeOf 和 Length 的返回值可能是不同的
Copy(, , )返回的 SubString 基于字符元素
Pos(,)返回第一个字符元素的序号
操作


CompareStr()
CompareText()
...
FillChar()

FillChar(Rect, SizeOf(Rect), #0)
FillChar(WndClassEx, SizeOf(TWndClassEx), #0). 使用的时候注意 WndClassEx.cbSize := SizeOf(TWndClassEx)
Windows API

API 默认使用 WideString (*W)形态的版本
PChar()具有相同的语义
范例:

GetModuleFileName:
function ModuleFileName(Handle: HMODULE): string;
var
   Buffer: array[0..MAX_PATH] of Char;
begin
   SetString(Result, Buffer, GetModuleFileName(Handle, Buffer, Length(Buffer)));
end;

GetWindowText:
function WindowCaption(Handle: HWND): string;
begin
   SetLength(Result, 1024);
   SetLength(Result, GetWindowText(Handle, PChar(Result), Length(Result)));
end;

字符串索引:
function StripHotKeys(const S: string): string;
var
   I, J: Integer;
   LastChar: Char;
begin
   SetLength(Result, Length(S));
   J := 0;
   LastChar := #0;
   for I := 1 to Length(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;


接上文

依赖字符 Size 的代码结构:

在 Tiburon 中,下列列表中列出的这些函数和特性依赖字符 Size,并且已经包含了一个“轻便”的版本,迁移代码的时候只需要将列出的代码迁移到后面提供的轻便版本即可。


SizeOf() 替换为 Length()
范例:
var
   Count: Integer;
   Buffer: array[0..MAX_PATH - 1] of Char;
begin
   // 现有代码 - 当 string = UnicodeString 的时候这段代码是错的
   Count := SizeOf(Buffer);
   GetWindowText(Handle, Buffer, Count);
          
   // 正确的应该是下面这样
   Count := Length(Buffer); // <<-- Count 应该是 Chars 而不是 Bytes
   GetWindowText(Handle, Buffer, Count);
end;
SizeOf 返回的是数组的字节数,而 GetWindowText 的 Counts 参数需要的是字符数,所以这里需要把 SizeOf 换成 Length。

Move(... CharCount) 替换为 Move( ,,, CharCount * SizeOf(Char))
var
    Count: Integer;
    Buf1, Buf2: array[0..255] of Char;
begin
   // 现有代码 - 当 string = UnicodeString (char = 2 bytes) 时,下面的代码是错误的
   Count := Length(Buf1);
   Move(Buf1, Buf2, Count);
  
   // 正确的写法应该是
   Count := SizeOf(Buf1);           // <<-- Specify buffer size in bytes
   Count := Length(Buf1) * SizeOf(Char); // <<-- Specify buffer size in bytes
   Move(Buf1, Buf2, Count);
end;
由于 Length 返回的是字符数,而 Move 的 Count 参数需要的是字节数,所以应该用 SizeOf 或者 Length(Buf1) * SizeOf(Char) 替换 Length(Buf1)。

Stream 的 Read/Write 替换为 AnsiString, SizeOf(Char),或者使用 TEncoding 类
调用 Read/ReadBuffer 方法的范例:
var
   S: string;
   L: Integer;
   Stream: TStream;
   Temp: AnsiString;
begin
   // 现有代码- 当 string = 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));   // <<-- Specify buffer size in bytes
  
   //正确的 Ansi 写法如下
   Stream.Read(L, SizeOf(Integer));
   SetLength(Temp, L);           // <<-- 使用临时的变量 AnsiString
   Stream.Read(Pointer(Temp)^, L * SizeOf(AnsiChar));   // <<-- Specify buffer size in bytes
   S := Temp;           // <<-- 放宽 string 到 Unicode
end;
上面的解决方案依赖于您存储在 Stream 中的字符串的编码格式,更好的读取和转换他们建议使用 TEncoding 类。

调用 Write/WriteBuffer 的范例:
var
   S: string;
   Stream: TStream;
   Temp: AnsiString;
begin
   // 现有代码 - 当 string = UnicodeString 时它是错的
   Stream.Write(Pointer(S)^, Length(S));
  
   // 正确的读取 Unicode 的代码
   Stream.Write(Pointer(S)^, Length(S) * SizeOf(Char)); // <<-- Specify buffer size in bytes
  
   // 正确的读取 Ansi 的代码
   Temp := S;           // <<-- Use temporary AnsiString
   Stream.Write(Pointer(Temp)^, Length(Temp) * SizeOf(AnsiChar));// <<-- Specify buffer size in bytes
end;
上面的解决方案依赖于您要存储进 Stream 中的字符串的编码格式,建议使用 TEncoding 类来更好的对格式进行处理。

FillChar(, , ) 如果采用 #0 填充, 替换为   * SizeOf(Char);如果填充其它字符,替换为 StringOfChar 函数
范例:
var
   Count: Integer;
   Buffer: array[0..255] of Char;
begin
    // 现有代码 - 当 string = UnicodeString ( char = 2 字节) 时,这段代码是错的
    Count := Length(Buffer);
    FillChar(Buffer, Count, 0);
          
    // 正确的代码应该写作下面这样
    Count := SizeOf(Buffer);           // <<-- Specify buffer size in bytes
    Count := Length(Buffer) * SizeOf(Char); // <<-- Specify buffer size in bytes
    FillChar(Buffer, Count, 0);
end;
Length 返回的是字符数,而 FillChar 的 Count 参数需要的是字节数,所以必须用 SizeOf 替换 Length,或者使用 Length * SizeOf(Char)。

另外,需要注意的是,Tiburon 中 Char 等于 2 个字节,FillChar 填充的时候确是按照 Bytes 来计算的,所以,下面的代码

var
   Buf: array[0..32] of Char;
begin
   FillChar(Buf, Length(Buf), #9);
end;

并不是向目标中填充 $09,而是 $0909,要得到正确的数值,应该改写成下面这样:

var
   Buf: array[0..32] of Char;
begin
   StrPCopy(Buf, StringOfChar(#9, Length(Buf)));
...
end;

GetProcAddress(, )  
由于 GetProcAddres 没有对应的 *W (Unicode) 版本的 API,所以只能使用下面的代码来正确调用它:
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;


RegQueryValueEx 函数
由于 RegQueryValueEx 函数的 Len 指定的是字节数,而不是字符数,所以 Unicode 版本中它的大小是实际需要大小的 2 倍,所以这样的代码:

Len := MAX_PATH;
if RegQueryValueEx(reg, PChar(Name), nil, nil, PByte(@Data[0]), @Len) = ERROR_SUCCESS
then
   SetString(Result, Data, Len - 1) // Len includes #0
else
   RaiseLastOSError;

应该换成下面这样:

Len := MAX_PATH * SizeOf(Char);
if RegQueryValueEx(reg, PChar(Name), nil, nil, PByte(@Data[0]), @Len) = ERROR_SUCCES
then
   SetString(Result, Data, Len div SizeOf(Char) - 1) // Len includes #0, Len contains the number of bytes
else
   RaiseLastOSError;

CreateProcessW 函数
在 Unicode 版本的 CreateProcess 函数中,其行为和 ANSI 的版本略有不同。Unicode 的CreateProcessW 会改变参数 lpCommandLine 传入的数据,因此调用 CreateProcess /CreateProcessW 的时候,不可以给 lpCommandLine 赋值常量,或者是一个变量指向的常量,否则函数会抛出 accessviolations 的异常。下面是错误的代码:

// 传入了一个 string 常量
CreateProcess(nil, 'foo.exe', nil, nil, False, 0,
   nil, nil, StartupInfo, ProcessInfo);

// 传入了一个常量表达式
   const
     cMyExe = 'foo.exe'
   CreateProcess(nil, cMyExe, nil, nil, False, 0,
     nil, nil, StartupInfo, ProcessInfo);

// 传入了一个引用计数为 -1 的字符串:
const
   cMyExe = 'foo.exe'
var
   sMyExe: string;
   sMyExe := cMyExe;
   CreateProcess(nil, PChar(sMyExe), nil, nil, False, 0, nil, nil, StartupInfo, ProcessInfo);

LeadBytes 常量
早先的版本中 LeadBytes 常量包含了本地系统中所有可以作为双字节字符 LeadByte 的列表,常常有这样的代码:
if Str[I] in LeadBytes then

现在你需要将它改成调用 IsLeaderChar 函数
if IsLeadChar(Str[I]) then

使用 TMemoryStream 类
当您需要用 TMemoryStream 写入一个文本文件的时候,最好在写入任何字符数据进去之前先写入一个 Byte Order Mark (BOM):
var
   Bom: TBytes;
begin
   ...
   Bom := TEncoding.UTF8.GetPreamble;
   Write(Bom[0], Length(Bom));

而任何写入的字符需要被转换成 UTF-8 编码:
var
   Temp: Utf8String;
begin
   ...
   Temp := Utf8Encode(Str); // Str 是要写入文件的字符
   Write(Pointer(Temp)^, Length(Temp));
//Write(Pointer(Str)^, Length(Str)); 原来写入字符串的代码


接上文


MultiByteToWideChar 函数
调用 Windows API 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 下可以写作这样(同时支持 Unicode 和 ANSI 字符):

procedure TWideCharStrList.AddString(const S: string);
{$IFNDEF UNICODE}
var
   L, D: Integer;
{$ENDIF}
begin
{$IFDEF UNICODE}
   FList[FUsed] := StrNew(PWideChar(S));
{$ELSE}
   L := Length(S);
   D := (L + 1) * SizeOf(WideChar);
   FList[FUsed] := AllocMem(D);
   MultiByteToWideChar(0, 0, PAnsiChar(S), L, FList[FUsed], D);
{$ENDIF}
   Inc(FUsed);
end;

SysUtils.AppendStr 函数
AppendStr 函数已经废弃了,因为它与 AnsiString 硬编码在一起,而且没有 Unicode 的版本可以替换,所以下面的代码

AppendStr(String1, String2);

应该换成:

String1 := String1 + String2;

您也可以使用新的 TStringBuilder 类来替换。

使用 Named Threads
现有 Delphi 代码中使用了 Named Threads 的代码必须修改了。在早先的版本中,当你需要在分类(gallery)中用一个新的 Thread Object 去创建一个 Thread 的时候,需要在新的 Thread 单元中建立下面的类型:

type
TThreadNameInfo = record
   FType: LongWord; // must be 0x1000
   FName: PChar; // pointer to name (in user address space)
   FThreadID: LongWord; // thread ID (-1 indicates caller thread)
   FFlags: LongWord; // reserved for future use, must be zero
end;

在调试器中,Named Thread 的处理器期待 FName 成员是 ANSI 字符,不是 Unicode,所以上面的声明必须改成下面这样:

type
TThreadNameInfo = record
   FType: LongWord; // must be 0x1000
   FName: PAnsiChar; // pointer to name (in user address space)
   FThreadID: LongWord; // thread ID (-1 indicates caller thread)
   FFlags: LongWord; // reserved for future use, must be zero
end;

在新版本中上述声明已经修改,提示这段代码是需要您注意早先版本中您手工创建并声明的代码需要您自己修改。

如果您需要在 Named Thread 中使用 Unicode 字符,您必须将字符串格式化成 UTF-8 编码,调试器可以完全支持改编码。例如:

ThreadNameInfo.FName := UTF8String('UnicodeThread_фис');

注意:C++ Builder 里面一直使用的是正确的代码,所以上述问题在 C++ Builder 中并不存在。

使用 PChar 转换的指针运算
在 Tiburon 更早的版本中,并不是所有的指针类型都支持指针运算。因为这样,为了让无类型指针也支持指针运算,许多代码都将其转化成PChar 操作。现在,可以使用 Tiburon 中的新编译条件 {$POINTERMATH} 来指示编译器允许指针运算,特别是允许PByte 的指针运算。{$POINTERMATH ON/OFF} 可以打开/禁止对任意指针变量的运算,增减指针实际操作的是指针元素的大小。

下面的例子是一个将某类型指针转换成 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;

在上面的例子中,Node 真实的数据不是 PChar 的数据。将其强制转换成 PChar 的操作在早先的版本中是正常的,因为早先版本中SizeOf(Char) == Sizeof(Byte)。但是现在不同了,所以这样的代码必须从 PChar 改换成PByte。如果不做这样的更改,返回的 Pointer 将指向错误的数据。

变体开放数组(Variant Open Array)参数
如果你的代码中有使用 TVarRec 类型去处理开放数组的话,你可能需要为其添加对 vtUnicodeString 的支持。参看下列示例:

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;

其他需要注意的代码:

AllocMem(
AnsiChar
of AnsiChar
AnsiString
of Char
Copy(
GetMem(
Length(
PAnsiChar(
Pointer(
Seek(
ShortString
string[
代码中包含上述写法的地方可能需要修改以适应 UnicodeString 的变化。


带字符的集合类型

您可能需要修改下列类型:

in AnsiChar> 这样的代码生成的程序是正确的(>#255 的字符不会包含在集合内)。编译器会提出 "WideCharreduced in set operations" 的警告,基于您代码的需要,您可以关闭这个警告,或者使用 CharInSet 函数替代。
in LeadBytes 全局的 LeadBytes 变量包含的是本地 MBCS Ansi 字符的集合。UTF-16 格式也有LeadChar 的概念((#$D800 - #$DBFF 是高 surrogate, #$DC00 - #$DFFF 是低surrogate)。因此建议使用 overload 函数 IsLeadChar 来判断,该函数的 ANSI 版本检测LeadBytes,WideChar 版本检测 high/low surrogate。
字符分类 使用静态类 TCharacter。Character 单元中提供了一些函数对字符分类:IsDigit, IsLetter, IsLetterOrDigit, IsSymbol, IsWhiteSpace, IsSurrogatePair,等等。
应当心这些结构

您需要检查下列可能引起错误的结构:

模糊的类型转换

AnsiString(Pointer(foo))
检查正确性:代码是什么意图?
可疑的类型转换引发的警告

PChar()
PAnsiChar()
直接建立、操作、访问 string 的内部结构。例如 AnsiString 的内部结构已经发生变化,所以这样的操作是危险的。您应该使用StringRefCount, StringCodePage, StringElementSize 等方法来获得额外信息。
控件和类

TStrings: 内部存储的是 UnicodeStrings。
TWideString:(可能被废弃)没有更改,内部使用 WideString (BSTR)
TStringStream

被重写成内部存储 ANSI 字符
字符编码可以被重载
考虑使用 TStringBuilder 替代 TStringStream 来逐步构建字符串
TEncoding

Default 属性是用户活动页码(users’ active code page)
支持 UTF-8
支持 UTF-16, big 和 little endian
支持 Byte Order Mark (BOM)
您可以继承子类实现特殊的编码
Byte Order Mark

BOM 必须添加到文件中以便判断文件的编码方式。

UTF-8 使用 EF BB EF
UTF-16 Little Endian 使用 FF FE
UTF-16 Big Endian 使用 FE FF
做好这些注意事项,将帮助您顺利地把旧有项目迁移到 Tiburon 的 Unicode 下。当然,如果您开发的是多版本控件,或者是希望项目能在多个版本中编译,您最好根据这些特性定义适当的编译条件,以便让代码更好的被更低的版本的编译器支持和编译。

本文基于 Tiburon 帮助编写,如有翻译错误或描述不准确的地方欢迎大家指正!相信这次 Delphi / C++ Builder 2009 将是广大爱好者最喜欢的版本之一。

全文完。

 

 

 

 

原出处:http://hi.baidu.com/tifish/blog/item/bf28dbcf993f9835f9dc6172.html

 

Delphi 2009是第一个完整支持Unicode的Delphi版本。虽然来得太迟,但确是巨大的进步。

原来的Delphi中有两种字符串:AnsiString和WideString。默认的string即AnsiString。而在Delphi2009中,新增加了一种UnicodeString。为什么不沿用之前的WideString呢?WideString其实是为了方便使用COM而产生的,就是BSTR。BSTR没有引用计数,效率较低。而UnicodeString才是AnsiString的真正unicode版本。

于是,Delphi 2009就有了三种字符串类型:AnsiString、WideString、UnicodeString。默认的string即为UnicodeString。对应的相关类型包括:
AnsiString - PAnsiChar - TAnsiString?(这个可以有……这个真没有,JclAnsiStrings.pas是一个替代品)
WideString - PWideChar - TWideStrings(WideStrings.pas)
UnicodeString - PWideChar - TStrings(Classes.pas)

在实际应用中,一般应使用UnicodeString。在效率第一的场合,可以使用AnsiString处理Ansi文本。而WideString仅在使用COM的时候才需要,或者是为了向下兼容。

几个字符串相关unit的作用:(D2009有点乱)
StrUtils.pas:UnicodeString的处理函数。
AnsiStrings.pas:AnsiString的处理函数。
WideStrUtils.pas:WideString的处理函数。
WideStrings.pas:TWideStringList的实现。
Classes.pas:TStringList的实现。
JclAnsiStrings.pas:TJclAnsiStringList的实现。这个虽然是第三方库,但不得不提,谁让CodeGear好死赖活不肯加呢。

Delphi 2009的VCL完全使用UnicodeString,彻底支持Unicode。TNT UnicodeControls终于完成了光辉的历史使命。VCL设计之初不支持Unicode情有可原,但多年以后,在国际化的大潮中,依然没有改变,就是重大失误了。13年的等待,黄花菜都凉了。不论如何,今日的Delphier,可以放心大胆的使用Unicode了。

关于UTF8String。UTF8String在之前的版本中就是AnsiString,没有什么特殊功能。而在Delphi2009中,UTF8String才是真正的UTF8。如果把一个AnsiString赋值给一个UTF8String,那么Delphi2009会自动转换格式为UTF8String,这比以前可要方便多了。

关于RawByteString。这个在某些场合有用。如果你有一个函数,接受AnsiString或者UTF8String,但不希望发生自动转换,那么可以通过重载,实现两个函数分别处理AnsiString和UTR8String。另一个选择就是使用RawByteString,那么不管传过来的是AnsiString还是UTF8String,RawByteString都会忠实的保持原样,不会做任何转换。

可以参考的官方资料:《Delphi and Unicode》

 

 

 

原创粉丝点击