SysUtils单元详解

************************系统实用例程********************************

Delphi / Kylix 跨平台运行时库(System Utilities)

Copyright (c) 1995-2002 Borland Softwrare Corporation

*******************************************************************

SysUtils单元;

1. 常量(Const

1) 文件打开方式

{$以下用于Linux环境}

fmOpenRead = O_RDONLY;

fmOpenWrite = O_WRONLY;

fmOpenReadWrite = O_RDWR;

// fmShareCompat 不被支持

fmShareExclusive = $0010;

fmShareDenyWrite = $0020;

// fmShareDenyRead 不被支持

fmShareDenyNone = $0030;

{$ENDIF}

{$以下用于MsWindows}

fmOpenRead = $0000;

fmOpenWrite = $0001;

fmOpenReadWrite = $0002;

fmShareCompat = $0000 platform; // DOS 兼容模式不portable

fmShareExclusive = $0010;

fmShareDenyWrite = $0020;

fmShareDenyRead = $0030 platform; // 只写在所有平台上都不被支持

fmShareDenyNone = $0040;

{$ENDIF}

2) 文件属性

faReadOnly = $00000001 platform;

faHidden = $00000002 platform;

faSysFile = $00000004 platform;

faVolumeID = $00000008 platform;

faDirectory = $00000010;

faArchive = $00000020 platform;

faSymLink = $00000040 platform;

faAnyFile = $0000003F;

3) 时间单位

HoursPerDay = 24; 每天24小时

MinsPerHour = 60; 每小时60分

SecsPerMin = 60; 每分钟60秒

MSecsPerSec = 1000; 每秒1000毫秒

MinsPerDay = HoursPerDay * MinsPerHour; 每天的分钟数

SecsPerDay = MinsPerDay * SecsPerMin; 每天秒数

MSecsPerDay = SecsPerDay * MSecsPerSec; 每天毫秒数

DateDelta = 693594; 每天介于 1/1/0001 和 12/31/1899 之间

UnixDateDelta = 25569; { 介于TDateTime 基数(12/31/1899) 和Unix time_t 基数(1/1/1970)之间的天数 }

2. 类型定义(type

TSysCharSet = set of Char; //设置字符类型标准:所有ANSI字符的集合

TIntegerSet = set of 0..SizeOf(Integer) * 8 - 1; { 设定整数的访问类型:0-31的整数集合 }

//类型转换

// WordRec使访问一个Word类型变量或者其他16位变量(SmallInt)的高位和低位字节变得更容易

WordRec = packed record

case Integer of

0: (Lo, Hi: Byte);

1: (Bytes: array [0..1] of Byte);

end;

LongRec使访问一个LongWord类型变量或者其它32位变量(Single)高位和低位字变得更容易。

LongRec = packed record

case Integer of

0: (Lo, Hi: Word);

1: (Words: array [0..1] of Word);

2: (Bytes: array [0..3] of Byte);

end;

Int64Rec使访问一个Int64类型变量或者其它64位变量(Double)高位和低位字变得更容易。

Int64Rec = packed record

case Integer of

0: (Lo, Hi: Cardinal);

1: (Cardinals: array [0..1] of Cardinal);

2: (Words: array [0..3] of Word);

3: (Bytes: array [0..7] of Byte);

end;

//一般数组

PByteArray = ^TByteArray;

TByteArray = array[0..32767] of Byte;

PWordArray = ^TWordArray;

TWordArray = array[0..16383] of Word;

TProcedure = procedure; //一般程序指针

TFileName = type string; //一般文件类型

TSearchRec = record //用于搜索记录的结构(由函数 FindFirst, FindNext, 和 FindClose 使用)

Time: Integer;

Size: Integer;

Attr: Integer;

Name: TFileName;

ExcludeAttr: Integer;

{$以下用于MsWindows平台}

FindHandle: THandle platform;

FindData: TWin32FindData platform;

{$ENDIF}

{$以下用于Linux环境}

Mode: mode_t platform;

FindHandle: Pointer platform;

PathOnly: String platform;

Pattern: String platform;

{$ENDIF}

end;

TFloatValue = (fvExtended, fvCurrency); 浮点类型格式化代码

TFloatFormat = (ffGeneral, ffExponent, ffFixed, ffNumber, ffCurrency); FloatToText格式化代码

TFloatRec = packed record // FloatToDecimal 结果的记录型结构

Exponent: Smallint;

Negative: Boolean;

Digits: array[0..20] of Char;

end;

TTimeStamp = record //日期和时间的记录结构

Time: Integer; 从0:00开始的的毫秒数

Date: Integer; {从1/1/0001以后的天的加数 }

end;

TMbcsByteType = (mbSingleByte, mbLeadByte, mbTrailByte); 多字节字符集的字节类型

TSysLocale = packed record //本地系统信息记录类型

DefaultLCID: Integer;

PriLangID: Integer;

SubLangID: Integer;

FarEast: Boolean;

MiddleEast: Boolean;

end;

{$以下用于MsWindows平台}

TLangRec = packed record //被使用的语言

FName: string;

FLCID: LCID;

FExt: string;

end;

TLanguages = class //存储系统支持的语言

private

……..

Public

…….

end platform;

{$ENDIF}

{以下用于Linux环境}

TEraRange = record

StartDate : Integer; // 从12/31/1899 (TDateTime 基数)的全部天数

EndDate : Integer; //从12/31/1899 (TDateTime 基数)的全部天数

Direction : Char;

end;

{$ENDIF}

Exception = class(TObject) //异常

private

……..

public

……….

end;

ExceptClass = class of Exception;

EAbort = class(Exception);

EHeapException = class(Exception)

private

AllowFree: Boolean;

public

procedure FreeInstance; override;

end;

EOutOfMemory = class(EHeapException);

EInOutError = class(Exception)

public

ErrorCode: Integer;

end;

{以下用于MsWindows平台}

PExceptionRecord = ^TExceptionRecord;

TExceptionRecord = record

ExceptionCode: Cardinal;

ExceptionFlags: Cardinal;

ExceptionRecord: PExceptionRecord;

ExceptionAddress: Pointer;

NumberParameters: Cardinal;

ExceptionInformation: array[0..14] of Cardinal;

end;

{$ENDIF}

EExternal = class(Exception)

public

{$以下用于MsWindows平台}

ExceptionRecord: PExceptionRecord platform;

{$ENDIF}

{$以下用于Linux环境}

ExceptionAddress: LongWord platform;

AccessAddress: LongWord platform;

SignalNumber: Integer platform;

{$ENDIF}

end;

EExternalException = class(EExternal);

EIntError = class(EExternal);

EDivByZero = class(EIntError);

ERangeError = class(EIntError);

EIntOverflow = class(EIntError);

EMathError = class(EExternal);

EInvalidOp = class(EMathError);

EZeroDivide = class(EMathError);

EOverflow = class(EMathError);

EUnderflow = class(EMathError);

EInvalidPointer = class(EHeapException);

EInvalidCast = class(Exception);

EConvertError = class(Exception);

EAccessViolation = class(EExternal);

EPrivilege = class(EExternal);

EStackOverflow = class(EExternal) end deprecated;

EControlC = class(EExternal);

{以下用于Linux环境}

EQuit = class(EExternal) end platform;

{$ENDIF}

{以下用于Linux环境}

ECodesetConversion = class(Exception) end platform;

{$ENDIF}

EVariantError = class(Exception);

EPropReadOnly = class(Exception);

EPropWriteOnly = class(Exception);

EAssertionFailed = class(Exception);

{$IFNDEF PC_MAPPED_EXCEPTIONS}

EAbstractError = class(Exception) end platform;

{$ENDIF}

EIntfCastError = class(Exception);

EInvalidContainer = class(Exception);

EInvalidInsert = class(Exception);

EPackageError = class(Exception);

EOSError = class(Exception)

public

ErrorCode: DWORD;

end;

{以下用于MsWindows平台}

EWin32Error = class(EOSError)

end deprecated;

{$ENDIF}

ESafecallException = class(Exception);

{以下用于Linux环境}

3. 符号(Signals)

外部异常或符号由Delphi RTL默认被转换到语言异常。在Linux下,一个Delphi应用程序安装符号处理机来诱捕原始符号并转换他们。Delphi库默认不安装处理机。所以你要是执行一个标准库,类似Apache DSO, 你想要将符号转换到能够捕获的语言异常,就必须人工安装符号钩,用Delphi RTL提供的接口。

对于大多数的库,安装符号处理机是恰当简便的。在初始时间调用HookSignal(RTL_SIGDEFAULT),在关闭时调用UnhookSignal(RTL_SIGNALDEFAULT),将会为一组符号安装处理机,Delphi应用程序被RTL正常钩住。

有时候会有一些使以上的初始化不能工作的事情。适当的设置一个符号处理机的行为,然后当整理完后恢复到以前状态。如果你有两个库lib1和lib2,lib1安装了符号处理机,然后lib2也安装了一个,如果要恢复符号处理机则那些库就必须以适当的次序卸载,或者符号处理机能够被留在矛盾而致命的地方。为了防止这种可能,允许你无论在何种情况下在外部库中发现这种行为都能较好的管理符号处理机,我们提供了一组4个接口来容许你在紧急事件中剪裁Delphi符号处理机挂钩/脱钩,他们是:

InquireSignal

AbandonSignalHandler

HookSignal

UnhookSignal

InquireSignal 允许你看符号处理机的状态,也就是你能发现在你之下抓取它的人。

AbandonSignalHandler 告诉RTL从不脱钩一个特定的符号处理机。如果你发现一个符号处理机将要不安全的返回到以前状态就需要使用它。例如,如果前一个符号处理机被一个后来被卸载的库安装。

HookSignal/UnhookSignal 设置符号处理机映射某个信号为语言异常。其它的看下面的InquireSignal等注释。

const

RTL_SIGINT = 0; // 用户中断User interrupt (SIGINT)

RTL_SIGFPE = 1; // 浮点异常(SIGFPE)

RTL_SIGSEGV = 2; // 分割违背 (SIGSEGV)

RTL_SIGILL = 3; //非法指令(SIGILL)

RTL_SIGBUS = 4; // 总线Bus 错误 (SIGBUS)

RTL_SIGQUIT = 5; // 用户中断(SIGQUIT)

RTL_SIGLAST = RTL_SIGQUIT; // 已用于内部,不能用

RTL_SIGDEFAULT = -1; // 意味着我们捕获一组符号Means all of a set of signals that the we capture

// normally. 这是当前全部进程

// signals. 你不能传递这个到InquireSignal.

type

//TSignalState 给定的符号处理机的状态,由InquireSignal送回。看以下InquireSignal。

TSignalState = (ssNotHooked, ssHooked, ssOverridden);

var

如果DeferUserInterrupts设置,我们不能引发SIGINT 、SIGQUIT 这样的异常,而是当信号到达时设置SIGINTIssued或SIGQUITIssued,并且要忍受OS发出的信号。这个引起GUI 应用程序偶然的延迟实际信号处理直到它是安全

DeferUserInterrupts: Boolean;

SIGINTIssued: Boolean;

SIGQUITIssued: Boolean;

{$ENDIF}

{$以下用于Linux环境}

const

MAX_PATH = 4095; // From /usr/include/linux/limits.h PATH_MAX

{$ENDIF}

var

{ 空字串和null 字符指针.这些常量只为向后兼容而提供。 }

EmptyStr: string = '';

NullStr: PString = @EmptyStr;

EmptyWideStr: WideString = '';

NullWideStr: PWideString = @EmptyWideStr;

{$以下用于MsWindows平台}

Win32 平台标识符,将会是下列数值之一:

VER_PLATFORM_WIN32s

VER_PLATFORM_WIN32_WINDOWS

VER_PLATFORM_WIN32_NT

Win32Platform: Integer = 0; //数值看WINDOWS.PAS

Win32 OS 版本信息见TOSVersionInfo.dwMajorVersion/dwMinorVersion/dwBuildNumber

Win32MajorVersion: Integer = 0;

Win32MinorVersion: Integer = 0;

Win32BuildNumber: Integer = 0;

Win32CSDVersion: string = ''; // Win32 OS 以外版本信息字符串见TOSVersionInfo.szCSDVersion

4. 实用函数过程

1) Win32 OS 版本测试函数

function CheckWin32Version(AMajor: Integer; AMinor: Integer = 0): Boolean;

GetFileVersion 返回一个32位的文件的二进制版本数,它一般有助版本号和辅版本号,一般没有release 或build 号。 如果失败,则返回Cardinal(-1)

function GetFileVersion(const AFileName: string): Cardinal;

{$ENDIF}

2) 货币和日期/时间格式化选项

这些变量初始数值用Win32 API 中的GetLocaleInfo 函数从系统注册表取得,每个变量指定常量LOCALE_XXXX的来描述这些初始值

CurrencyString – 定义浮点数转换为十进制数后的需用的货币符号,初始值来自于LOCALE_SCURRENCY.

CurrencyFormat -定义浮点数转换为十进制数后的货币符号的位置和分离程度,可能的值为:

0 = '$1'

1 = '1$'

2 = '$ 1'

3 = '1 $'

初始值来自于LOCALE_ICURRENCY.

NegCurrFormat –定义负数浮点数转换为十进制数后的货币格式,可能的值为:

0 = '($1)' 4 = '(1$)' 8 = '-1 $' 12 = '$ -1'

1 = '-$1' 5 = '-1$' 9 = '-$ 1' 13 = '1- $'

2 = '$-1' 6 = '1-$' 10 = '1 $-' 14 = '($ 1)'

3 = '$1-' 7 = '1$-' 11 = '$ 1-' 15 = '(1 $)'

初始值来自于LOCALE_INEGCURR.

ThousandSeparator – 多于一千时的千分位分离符位于数值的左边,初始值来自于LOCALE_STHOUSAND. #0 值即使有此指示符也不应当输出指示符

DecimalSeparator – 用于分离一个数的小数部分的整数,其初值来自LOCALE_SDECIMAL. DecimalSeparator 必须是个非零值

CurrencyDecimals – 货币值中小数点右边的小数位数,初值来自LOCALE_ICURRDIGITS.

DateSeparator – 分离符:用于分离日期数值的年、月、日部分,初值来自于LOCATE_SDATE.

ShortDateFormat – 用于将日期型数值转换为适合编辑的短字符串。对日期和时间格式化字符串的完整描述,请查阅FormatDate 函数。短日期格式应当只使用日期分离符和m, mm, d, dd, yy, 和 yyyy 格式特定。初值来自于LOCALE_SSHORTDATE。

LongDateFormat -用于将日期型数值转换为适合显示而不是编辑的长字符串。对日期和时间格式化字符串的完整描述,请查阅FormatDate 函数。其初值来自于LOCALE_SLONGDATE。

TimeSeparator – 用于分离时间型数值的时、分、秒。其初值来自于LOCALE_STIME.。

TimeAMString – 时间后缀用于在12小时制上午的后缀,初值来自于LOCALE_S1159。

TimePMString – 12小时制下午的后缀,初值来自于LOCALE_S2359。

ShortTimeFormat – 此格式化字符用于时间值转换为只有小时和分钟的短字符串。其默认值从LOCALE_ITIME 和 LOCALE_ITLZERO计算得到

LongTimeFormat -此格式化字符用于时间值转换为含有小时、分钟和秒的长短字符串。其默认值从LOCALE_ITIME 和 LOCALE_ITLZERO计算得到。

ShortMonthNames – 字符串数组包含有短月份名,格式字串中的 mmm 特定格式被传送给FormatDate 会使得短月份名被替换。其默认值从 LOCALE_SABBREVMONTHNAME 系统本地入口取出。

LongMonthNames -字符串数组包含有长月份名。格式化字串中的mmmm 格式特定符被传送给FormatDate 会使得长月份名被替换。其缺省值是从LOCALE_SMONTHNAME 系统本地入口取出。

ShortDayNames -字符串数组包含有短天名,格式字串中的 ddd特定格式被传送给FormatDate 会使得短天名被替换。其默认值取自于LOCALE_SABBREVDAYNAME 系统本地入口。

LongDayNames -字符串数组包含有长天名,格式字串中的 dddd特定格式被传送给FormatDate 会使得长天名被替换。其默认值取自于LOCALE_SDAYNAME 系统本地入口。

ListSeparator – 字符用于分开一个列表的项目,其初值来自于LOCALE_SLIST。

TwoDigitYearCenturyWindow – 当将字符型日期转换为数字日期时,世纪被添加到两位的年中。这个值在提取世纪值之前被从本年度减去。这能延长现有的存依赖于2位数年数据登录项的应用程序寿命。对2000年(Y2k) 问题的最好的解决办法是不再接受两位数的年,在数据登录项中只接受4位的年,从而根本上消除世纪的模糊性

示例:

Current TwoDigitCenturyWindow Century StrToDate() of:

Year Value Pivot '01/01/03' '01/01/68' '01/01/50'

-------------------------------------------------------------------------

1998 0 1900 1903 1968 1950

2002 0 2000 2003 2068 2050

1998 50 (default) 1948 2003 1968 1950

2002 50 (default) 1952 2003 1968 2050

2020 50 (default) 1970 2003 2068 2050

var

CurrencyString: string;

CurrencyFormat: Byte;

NegCurrFormat: Byte;

ThousandSeparator: Char;

DecimalSeparator: Char;

CurrencyDecimals: Byte;

DateSeparator: Char;

ShortDateFormat: string;

LongDateFormat: string;

TimeSeparator: Char;

TimeAMString: string;

TimePMString: string;

ShortTimeFormat: string;

LongTimeFormat: string;

ShortMonthNames: array[1..12] of string;

LongMonthNames: array[1..12] of string;

ShortDayNames: array[1..7] of string;

LongDayNames: array[1..7] of string;

SysLocale: TSysLocale;

TwoDigitYearCenturyWindow: Word = 50;

ListSeparator: Char;

3) 线程安全流通和日期/时间格式化

TFormatSettings 记录型被设计成允许线程安全格式化,相同的全局变量描述在上面。每个使用全局变量被重载的格式化例程都需要TformatSettings型的附加参数。

一个TFormatSettings 记录型在使用之前必须有内容。使用GetLocaleFormatSettings函数能够使其基于给定环境。注意一些格式指定符仍然需要指定线程现场设置(类似于period/era 名字)。

type

TFormatSettings = record

CurrencyFormat: Byte;

NegCurrFormat: Byte;

ThousandSeparator: Char;

DecimalSeparator: Char;

CurrencyDecimals: Byte;

DateSeparator: Char;

TimeSeparator: Char;

ListSeparator: Char;

CurrencyString: string;

ShortDateFormat: string;

LongDateFormat: string;

TimeAMString: string;

TimePMString: string;

ShortTimeFormat: string;

LongTimeFormat: string;

ShortMonthNames: array[1..12] of string;

LongMonthNames: array[1..12] of string;

ShortDayNames: array[1..7] of string;

LongDayNames: array[1..7] of string;

TwoDigitYearCenturyWindow: Word;

end;

const

MaxEraCount = 7;

var

EraNames: array [1..MaxEraCount] of string;

EraYearOffsets: array [1..MaxEraCount] of Integer;

{以下用于Linux环境}

EraRanges : array [1..MaxEraCount] of TEraRange platform;

EraYearFormats: array [1..MaxEraCount] of string platform;

EraCount: Byte platform;

{$ENDIF}

const

PathDelim = {$IFDEF MSWINDOWS} '/'; {$ELSE} '/'; {$ENDIF}

DriveDelim = {$IFDEF MSWINDOWS} ':'; {$ELSE} ''; {$ENDIF}

PathSep = {$IFDEF MSWINDOWS} ';'; {$ELSE} ':'; {$ENDIF}

{以下用于MsWindows平台}

function Languages: TLanguages;

{$ENDIF}

4) 内存管理例程

AllocMem-在堆上分配给定大小的块。被分配的缓冲区设置为0。若要消除这个缓冲区请使用FreeMem 标准过程。

function AllocMem(Size: Cardinal): Pointer;

5) 退出过程处理

把给定的过程添加到运行时库的退出过程列表中。当应用程序终止时, 它的退出过程被执行,执行顺序是最后的过程先运行,也就是后进先出。

procedure AddExitProc(Proc: TProcedure);

6) 字符串处理例程

function NewStr(const S: string): PString; deprecated; //在堆上分配一个字串,只是为向后兼容而提供。

procedure DisposeStr(P: PString); deprecated; //消除一个由NewStr 分配的字串指针。只是为向后兼容而提供

procedure AssignStr(var P: PString; const S: string); deprecated; //赋值一个新的动态的已分配字串到给定的字串指针。只是为向后兼容而提供

procedure AppendStr(var Dest: string; const S: string); deprecated; //添加 S 到Dest 的末尾.(Dest := Dest + S)。只是为向后兼容而提供。

function UpperCase(const S: string): string; //转换给定的ASCII字符为大写,它只对7位的ASCII字符中的'a' - 'z' 起作用。 对于8位的国际字符集用AnsiUpperCase。

function LowerCase(const S: string): string; //转换给定的ASCII字符为小写,它只对7位的ASCII字符中的'A' - 'Z' 起作用。 对于8位的国际字符集用AnsiUpperCase。

function CompareStr(const S1, S2: string): Integer; //比较字串 S1 和 S2, 有大小写敏感(case-sensitivity). 如果S1<S2,返回值小于0;S1=S2,返回值等于0;S1>S2,返回值大小于。这个比较操作是基于每个字符的8位序数值并且不受当前的用户环境影响

function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler; //比较由P1和P2分别指示的Length长度的内存区域。如果相同则返回True 。

function CompareText(const S1, S2: string): Integer; //比较S1 和S2, 没有大小写敏感(case-sensitivity)。返回值与CompareStr类同。这个比较操作是基于每个字符的8位序数值('a'..'z' 变为'A'..'Z' 后)并且不受当前的用户环境影响

function SameText(const S1, S2: string): Boolean; //比较S1 和S2,没有大小写敏感。如果S1=S2,返回true ,也就是如果CompareText 将返回0。SameText 象CompareText一样有8位限制 。

function AnsiUpperCase(const S: string): string; //转换给定字串中的全部字符为大写,这个转换使用用户环境。

function AnsiLowerCase(const S: string): string; //转换给定字串中的全部字符为小写,这个转换使用用户环境。

function AnsiCompareStr(const S1, S2: string): Integer; 比较S1和S2,有大小写敏感。这个比较操作受控于用户当前环境。返回值与CompareStr相同。

function AnsiSameStr(const S1, S2: string): Boolean; //比较S1和S2,有大小写敏感。这个比较操作受控于用户当前环境。如果AnsiCompareStr返回0,则它返回True。

function AnsiCompareText(const S1, S2: string): Integer; //比较S1和S2,没有大小写敏感。这个比较操作受控于用户当前环境。返回值与CompareStr相同。

function AnsiSameText(const S1, S2: string): Boolean; //比较S1 和S2, 没有大小写敏感。这个比较操作受控于用户当前环境。如果AnsiCompareText返回0,则它返回True。

function AnsiStrComp(S1, S2: PChar): Integer; //比较S1 和S2,有大小写敏感。这个比较操作受控于用户当前环境。返回值与CompareStr相同。

function AnsiStrIComp(S1, S2: PChar): Integer; 比较S1和S2,没有大小写敏感。这个比较操作受控于用户当前环境。返回值与CompareStr相同。

function AnsiStrLComp(S1, S2: PChar; MaxLen: Cardinal): Integer; 比较S1和S2,有大小写敏感。最大直到MaxLen 长度。这个比较操作受控于用户当前环境。返回值与CompareStr相同。

function AnsiStrLIComp(S1, S2: PChar; MaxLen: Cardinal): Integer; 比较S1和S2,没有大小写敏感。最大直到MaxLen 长度。这个比较操作受控于用户当前环境。返回值与CompareStr相同。

function AnsiStrLower(Str: PChar): PChar; 转换给定字串的全部字符为小写,使用用户当前环境。

function AnsiStrUpper(Str: PChar): PChar; 转换给定字串的全部字符为大写,使用用户当前环境。

function AnsiLastChar(const S: string): PChar; 返回一个指到字串中的最后字符。这个函数支持多字节字符集

function AnsiStrLastChar(P: PChar): PChar; 返回一个指到字串中的最后字符。这个函数支持多字节字符集。

function WideUpperCase(const S: WideString): WideString; 转换给定字串的全部字符为大写。

function WideLowerCase(const S: WideString): WideString; 转换给定字串的全部字符为小写。

function WideCompareStr(const S1, S2: WideString): Integer; 比较S1 和S2,有大小写敏感。返回值与CompareStr相同。

function WideSameStr(const S1, S2: WideString): Boolean; 比较S1 和S2,有大小写敏感。如果WideCompareStr返回0,则它返回True。

function WideCompareText(const S1, S2: WideString): Integer; 比较S1 和S2,没有大小写敏感。返回值与CompareStr相同。

function WideSameText(const S1, S2: WideString): Boolean; 比较S1 和S2,没有大小写敏感。如果WideCompareText返回0,则它返回True。

function Trim(const S: string): string; overload; 从给定字串中去除首尾空格和控制符。

function Trim(const S: WideString): WideString; overload; 从给定字串中去除首尾空格和控制符。

function TrimLeft(const S: string): string; overload; 从给定字串中去除首端空格和控制符。

function TrimLeft(const S: WideString): WideString; overload; 从给定字串中去除首端空格和控制符。

function TrimRight(const S: string): string; overload; 从给定字串中去除尾空格和控制符。

function TrimRight(const S: WideString): WideString; overload; 从给定字串中去除尾空格和控制符。

function QuotedStr(const S: string): string; 返回加引号的字串。单引号分别被插入到字串的首尾端,并且对于字串中只有一个单引号,另一个都被添加。

function AnsiQuotedStr(const S: string; Quote: Char): string; 返回加给定引号字符的字串。引号分别被插入到字串的首尾端,并且字串中每个引号都是成对的。这个函数支持多字节字符集 (MBCS)。

function AnsiExtractQuotedStr(var Src: PChar; Quote: Char): string; 去除字符串的首尾引号,如果源字串首字符不是引号,则返回一个空的字串。函数从源串首端复制到遇到第二个引号或第一个零(Null)字符为止。这个源参数指向首个引号后面的字符串。如果源字串不包含有相匹配的结束引号,则其被指向最终的Null字符,这个函数支持多字节字符(MBCS)。

function AnsiDequotedStr(const S: string; AQuote: Char): string; 是AnsiExtractQuotedStr 函数的简化

{ AdjustLineBreaks 调整在给定的字串中所有的换行符为指定的格式。当格式是 tlbsCRLF 时,函数改变所有CR字符和LF字符为CR/LF对。当格式是 tlbsLF 的时候,函数改变所有的CR/LF对和CR字符为LF字符。 }

function AdjustLineBreaks(const S: string; Style: TTextLineBreakStyle ={以下用于Linux环境} tlbsLF {END Linux环境}{以下用于MSWINDOWS环境} tlbsCRLF {END MSWINDOWS环境}): string;

function IsValidIdent(const Ident: string): Boolean; 若给定字串是有效的标识符则返回为True。标识符是由['A'..'Z', 'a'..'z', '_']开始的并可能跟随['A'..'Z', 'a'..'z','0..'9', '_']的有效字串。

{ IntToStr 转换给定的数值为十进制字串表示。}

function IntToStr(Value: Integer): string; overload;

function IntToStr(Value: Int64): string; overload;

{ IntToHex 用指定的最小位数转换给定数值为十六进制字串表示。}

function IntToHex(Value: Integer; Digits: Integer): string; overload;

function IntToHex(Value: Int64; Digits: Integer): string; overload;

{ StrToInt 转换给定字串为整数值,若字串不包含有效的数值,则产生一个EconvertError异常。 }

function StrToInt(const S: string): Integer;

function StrToIntDef(const S: string; Default: Integer): Integer;

function TryStrToInt(const S: string; out Value: Integer): Boolean; 出现错误返回False

{与上面函数类似的Int64 函数}

function StrToInt64(const S: string): Int64;

function StrToInt64Def(const S: string; const Default: Int64): Int64;

function TryStrToInt64(const S: string; out Value: Int64): Boolean;

var

TrueBoolStrs: array of String;

FalseBoolStrs: array of String;

const

DefaultTrueBoolStr = 'True'; // DO NOT LOCALIZE

DefaultFalseBoolStr = 'False'; // DO NOT LOCALIZE

StrToBool 转换给定的字串为布尔值。若字串不包含有效的数值,则产生一个EconvertError异常。

function StrToBool(const S: string): Boolean;

function StrToBoolDef(const S: string; const Default: Boolean): Boolean;

function TryStrToBool(const S: string; out Value: Boolean): Boolean;

function BoolToStr(B: Boolean; UseBoolStrs: Boolean = False): string; 依次转换布尔值为字串。其总是拾取TrueStrs/FalseStrs 队列的第一个元素。

function LoadStr(Ident: Integer): string; 从应用程序的可执行文件或关联的资源模块加载由Ident给出的字串资源。若字串资源不存在,则返回一个空串。

function FmtLoadStr(Ident: Integer; const Args: array of const): string; 从应用程序的可执行文件或关联的资源模块加载由Ident给出的字串资源。并且使用给定的格式主题。

7) { 文件管理例程}

function FileOpen(const FileName: string; Mode: LongWord): Integer; 使用指定的访问模式打开指定的文件。访问模式是由fmOpenXXXX和fmShareXXXX等形式的常量表示,若成功访问则返回一个正数表示的文件句柄,若返回-1则表示有错误。

{ FileCreate

function FileCreate(const FileName: string): Integer; overload; 用指定的名字建立一个新文件。若成功建立则返回一个正数表示的文件句柄,若返回-1则表示有错误。在Linux中,调用FileCreate(FileName, DEFFILEMODE)来建立。

{

function FileCreate(const FileName: string; Rights: Integer): Integer; overload; 这是FileCreate 的第二个版本,让你在刚建立的文件上指定存取权。这个存取权参数在Win32系统中被忽略

function FileRead(Handle: Integer; var Buffer; Count: LongWord): Integer; 读取Handle句柄指定的文件的Count 字节长度到Buffer指定的缓存中。返回实际读取的字节数,如果已到达文件末尾则它比Count 少。如果产生错误则返回-1

function FileWrite(Handle: Integer; const Buffer; Count: LongWord): Integer; 从Buffer缓冲区写Count字节到句柄Handle指定的文件。返回实际写入的字节数,如果产生错误则返回-1

FileSeek :句柄Handle给定的文件的指针移至相对于起点Origin偏移Offset的位置处,如果 Origin=0,则意味着从文件的开始处算起;Origin=1则表示从当前位置算起;Origin=2表示从文件结尾算起(EOF)。返回值是新的当前位置(相对于文件的开始处)。如果发生错误则返回-1。

function FileSeek(Handle, Offset, Origin: Integer): Integer; overload;

function FileSeek(Handle: Integer; const Offset: Int64; Origin: Integer): Int64; overload;

procedure FileClose(Handle: Integer); 关闭指定文件

function FileAge(const FileName: string): Integer; 返回指定文件的日期和时间戳。其返回值用FileDateToDateTime函数能够被转换为TdateTime值。如果文件不存在则返回-1。

function FileExists(const FileName: string): Boolean; 返回布尔值指示文件是否存在。

function DirectoryExists(const Directory: string): Boolean; 返回布尔值指示目录是否存在(并且是真实的目录)。

function ForceDirectories(Dir: string): Boolean; 确保一个指定路径的所有目录存在。如果哪一级目录不存在则建立(目录)。返回真值表明成功。如果当前用户在给定路径下没有足够的文件访问权来建立目录则会失败。

FindFirst 在Path路径中搜索具有Attr属性的第一个文件,结果被送回F(TsearchRec)。如果搜索成功则返回0,其它返回值是系统错误码,调用FindFirst后,总是调用FindClose。FindFirst 其后总是跟随FindNext 和FindClose 序列:

Result := FindFirst(Path, Attr, SearchRec);

while Result = 0 do

begin

ProcessSearchRec(SearchRec);

Result := FindNext(SearchRec);

end;

FindClose(SearchRec);

//ProcessSearchRec 是用户自定义代码

function FindFirst(const Path: string; Attr: Integer; var F: TSearchRec): Integer;

function FindNext(var F: TSearchRec): Integer; 返回符合条件(FindFirst序列)的下一个文件F。如果成功则返回0,其它返回值是系统错误码

procedure FindClose(var F: TSearchRec); 终止一个FindFirst/FindNext 序列,释放内存和系统资源。每个FindFirst/FindNext 序列必须由FindClose来结束

function FileGetDate(Handle: Integer): Integer; 返回由句柄给定的文件的OS日期时间戳。若句柄无效则返回-1。FileDateToDateTime函数能够将返回值转换为一个TdateTime值。

function FileSetDate(const FileName: string; Age: Integer): Integer; overload;设置由FileName指定的文件的OS日期时间戳为Age。DateTimeToFileDate函数可将TdateTime值转换为OS日期时间戳。如果成功则返回0,其它返回值是系统错误码

{以下用于MsWindows平台}

function FileSetDate(Handle: Integer; Age: Integer): Integer; overload; platform; 在Unix平台句柄是无效的,因为它不能只用一个句柄来设置文件的修改时间。也没有办法获得一个打开的文件的名字。

function FileGetAttr(const FileName: string): Integer; platform; 返回文件FileName的属性。这个属性能够使用前面已定义的faXXXX常量的AND-ing来检查,如果发生错误则返回-1

function FileSetAttr(const FileName: string; Attr: Integer): Integer; platform; 设置文件FileName的属性值为Attr,这个属性值是由OR-ing适当的faXXXX常量形成的。成功则返回0,其它返回值是系统错误码 。

{$ENDIF}

function FileIsReadOnly(const FileName: string): Boolean; 为当前进程和用户ID检查给定文件是否为只读。若文件不存在则返回False。(在调用FileIsReadOnly之前检查FileExists)这个函数是平台portable.

function FileSetReadOnly(const FileName: string; ReadOnly: Boolean): Boolean; 设置文件为只读。这个文件必须存在并且当前用户ID必须是文件的拥有者。在Unix系统中,这个函数试图设置或移除文件上全部三用户(user, group, and other)的写许可,如果想要同意局部的许可(只许所有者User),用平台指定函数如chmod。如果文件成功改变则返回True,有错误则返回False。这个函数是平台portable.

function DeleteFile(const FileName: string): Boolean; 删除文件FileName。若成功删除则返回True,有错误则返回False

function RenameFile(const OldName, NewName: string): Boolean; 将文件名OldName改名为NewName。成功改名则返回True,发生错误则返回False。

function ChangeFileExt(const FileName, Extension: string): string; 改变文件名FileName的扩展名为Extension,FileName可以有或无扩展名,Extension可以是一个空字串或一个以句点开头的最多三个字符的字串。

function ExtractFilePath(const FileName: string): string; 取出给定FileName的驱动器和目录部分。结果字串是FileName最左边的字符,包含有:和/分离符的路径信息。若FileName不包含驱动器和目录部分则返回空。

function ExtractFileDir(const FileName: string): string; 取出文件名的路径部分,去掉最后的反斜杠/,可以把本函数的结果给任何一个有关目录操作的函数使用。如果文件名不包含路径部分则返回空字符。

function ExtractFileDrive(const FileName: string): string; 返回文件名的盘符部分,或者是通用命名约定中的主机以及共享名,若文件名中不包含盘符,则返回空字串

function ExtractFileName(const FileName: string): string; 返回一个路径中的文件名部分,并且包含扩展名;若FileName以一个冒号或反斜杠结尾,则本函数返回空字串。

function ExtractFileExt(const FileName: string): string; 返回文件名的扩展名部分,并包括他的小数点,若没有扩展名则返回空字串

function ExpandFileName(const FileName: string): string; 返回文件的绝对路径包括盘符及目录

type

TFilenameCaseMatch = (mkNone, mkExactMatch, mkSingleMatch, mkAmbiguous);

function ExpandFileNameCase(const FileName: string; out MatchFound: TFilenameCaseMatch): string; 象ExpandFilename返回一个完整的的文件名, 但是,在区分大小写字母的文件系统中完全匹配搜索时执行的是大小写字母相同对待的策略。有益于懒惰用户输入便于使用的文件名, 或者用在不区分大小写系统(Win32)建立的文件名数据转换为用于区分大小的文件系统(Linux)时。输出参数 MatchFound 指出在文件系统搜索中查找了出何种匹配类型的文件,其结果基于以下:

(以难度或复杂性为序)

mkExactMatch: 区分大小写。 Result := ExpandFileName(FileName).

mkSingleMatch: 给定路径中不区分大小写方式严密匹配出一个文件Result := ExpandFileName(FileName as found in file system).

mkAmbiguous: 给定路径中不区分大小写方式匹配出许多文件,这要考虑错误问题Result := ExpandFileName(First matching filename found).

mkNone: 文件根本找不到Result := ExpandFileName(FileName).

注意,由于此函数要搜索文件系统,所以特殊情况下(文件名模糊或不存在)比ExpandFileName慢,当你输入了一个不确定的名字并且你想要最好的结果时才使用此函数。

function ExpandUNCFileName(const FileName: string): string; 返回一个充分扩展了绝对路径的文件名,磁盘符被扩展成通用命名约定(UNC),例如(//Server/sharename)

function ExtractRelativePath(const BaseName, DestName: string): string; 返回一个相对于给定
BaseName目录的路径DestName的文件名,在Windows中去除公共路径添加’../’,在Linux系统中则是‘../’

{以下用于MsWindows平台}

function ExtractShortPathName(const FileName: string): string; 将文件名转换为短文件名(8.3)。若FileName已是一个短文件名,则返回相同的文件名。若文件不存在,则返回一个空串。

{$ENDIF}

function FileSearch(const Name, DirList: string): string; 在DirList目录中,查找Name文件。查找通常由当前目录开始,然后再查找DirList中所列出的目录。其中目录之间用分号隔开,Name必须是一个单纯的文件名或是一个相对路径,函数返回的是整个路径名,若找不到文件则返回空字串。

{以下用于MsWindows平台}

function DiskFree(Drive: Byte): Int64; 返回磁盘上可用字节数。1为A盘,2为B盘,以此类推。Drive为0,则返回缺省盘的信息。此函数可有效的处理超过2GB的磁盘,除非在Win95A下,因为Win95A不支持大硬盘分区。如果磁盘无效则返回-1。

function DiskSize(Drive: Byte): Int64;返回磁盘整体字节数,参数同DiskFree

{$ENDIF}

function FileDateToDateTime(FileDate: Integer): TDateTime; 转换文件的‘修改时间’为TdateTime类型

{ DateTimeToFileDate converts a TDateTime value to an OS date-and-time

value. The FileAge, FileGetDate, and FileSetDate routines operate on OS

date-and-time values, and the Time field of a TSearchRec used by the

FindFirst and FindNext functions contains an OS date-and-time value. }

function DateTimeToFileDate(DateTime: TDateTime): Integer; 转换TdateTime类型为文件‘修改时间’

function GetCurrentDir: string; 返回当前的驱动器和工作目录。

function SetCurrentDir(const Dir: string): Boolean; 设置Dir为当前工作目录,成功返回True否则返回False。若不想在I/O结果上浪费时间,用此函数而不是ChDir。

function CreateDir(const Dir: string): Boolean; 创建Dir目录,成功返回True否则False。若不想在I/O结果上浪费时间,用此函数而不是MkDir。

function RemoveDir(const Dir: string): Boolean; 删除一个空的目录,返回True则成功,False

则失败。若不想在I/O结果上浪费时间,用此函数而不是RmDir。

8) PChar 例程

{const 参数帮助简化C++ 代码. 对pascal 代码无影响}

function StrLen(const Str: PChar): Cardinal; 返回Str的字符个数(即长度),不包括Null终结符

function StrEnd(const Str: PChar): PChar;返回指向Str终结符(Null)的指针

function StrMove(Dest: PChar; const Source: PChar; Count: Cardinal): PChar; 将Source字符串中Count个字节的内容完全复制到Dest中去。返回值是Dest,源缓冲区和目标缓冲区可以重叠。

function StrCopy(Dest: PChar; const Source: PChar): PChar; 将Source 中最多MaxLen个字节复制到Dest中去。必须确保Dest有足够的空间,返回Dest

function StrECopy(Dest:PChar; const Source: PChar): PChar; 将Source复制到Dest中去。返回指向Dest字串最后Null字符的指针

function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar; 将Source 中最多MaxLen个字符复制到Dest中去。如果Source是一个多字节字串,必须确保第MaxLen个字节没有落在一个多字节字符中间。

function StrPCopy(Dest: PChar; const Source: string): PChar; 将AnsiString字符串复制成为一个PChar字符串。必须确保Dest有足够空间,返回Dest

function StrPLCopy(Dest: PChar; const Source: string; MaxLen: Cardinal): PChar; 将AnsiString字串中最多MaxLen个字符复制Pchar字串。如果Source是一个多字节字串,必须确保第MaxLen个字节没有落在一个多字节字符中间。

function StrCat(Dest: PChar; const Source: PChar): PChar; 将Source复制到Dest尾部上去。必须确保Dest有足够空间,返回值Dest

function StrLCat(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar; 将Source 中最多MaxLen个字符复制到Dest尾部中去。如果Source是一个多字节字串,必须确保第MaxLen个字节没有落在一个多字节字符中间。返回值是Dest。

function StrComp(const Str1, Str2: PChar): Integer; 比较Str1和Str2。若Str1〈Str2则返回负数,Str1=Str2则返回0,Str1>Str2则返回正数。

function StrIComp(const Str1, Str2: PChar): Integer; 比较Str1和Str2。无大小写区别,返回值与StrComp相同

function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer; 比较Str1和Str2。字串最多Max:Len个字符,返回值与StrComp相同

function StrLIComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer; 比较Str1和Str2。无大小写区别,字串最多Max:Len个字符,返回值与StrComp相同

function StrScan(const Str: PChar; Chr: Char): PChar; 返回指向字串Str中第一个字符Char的指针,如果不存在则返回NIL。Null终结符也被算作字串的一部分。

function StrRScan(const Str: PChar; Chr: Char): PChar; 返回指向字串Str中最后一个字符Char的指针,如果不存在则返回NIL。Null终结符也被算作字串的一部分。

function StrPos(const Str1, Str2: PChar): PChar; 返回指向字串Str1中第一个字符串Str2的指针,如果不存在则返回NIL。

function StrUpper(Str: PChar): PChar; 转换Str为大写并返回

function StrLower(Str: PChar): PChar; 转换Str为小写并返回

function StrPas(const Str: PChar): string; 转换Str为Pascal型的字串。现在Delphi自动完成这个工作。此函数只是为向后兼容

function StrAlloc(Size: Cardinal): PChar; 在堆上分配一个大小为Size的缓冲区并返回它的指针,这个缓冲区并没有被初始化,要释放他,用StrDispose。

function StrBufSize(const Str: PChar): Cardinal; 返回由StrAlloc或者StrNew分配的字节数目。对于其它PChar函数不适用。

function StrNew(const Str: PChar): PChar; 在堆上分配空间给Str的备份并返回指向这个备份的指针。不要把本函数与NewStr函数混淆。可以用函数StrDispose函数来释放这个字符串。

procedure StrDispose(Str: PChar); 释放由StrNew和StrAlloc函数所分配内存的字符串。若Str是NIL,则什么都不做就返回。不要把它与DisposeStr函数相混淆。

9) 字符串格式化程序

{Format函数通过使用Format参数来格式化由Args参数中的variant开放数组。格式化字串包括无格式对象字符(objects—plain)和格式特定符两种类型。无格式字符被逐个的复制到结果字串中去,格式特定符从主题列表取出主题并且应用格式。

格式化特定符有以下形式

"%" [index ":"] ["-"] [width] ["." prec] type

一个格式特定符使用一个%开始,在其后是以下序列:

- [index ":"]:可选的Args的索引特定符。 当Index为0时表示第一个参数,若没有索引值则每个标识符对应于Args数组中连续的元素。使用索引值可以在一个格式字串中重复使用同一个参数,例如‘%d %d %0:d %d', [10, 20]’产生10 20 10 20的结果。

- ["-"]:可选的左对齐指示符。

- [width]:可选的宽度特定符。用来设定格式化后的字串字符个数。若实际格式化后的值长度小于Width个字符,则将会在字串的左边加上空格,如果在Width前使用-,则空格加在右边。

- ["." prec]可选的精度特定符。

- type:转换类型字符,是一个字母,大小写均可:

d :格式化一个有符号的十进制整数。Precision确定了要显示的数字的最小个数,并且还会在需要的时候在左边加上0。Args的值必须是一个整数。

u :格式化一个无符号十进制整数。其余与’d’类似

e :用科学计数(scientific)法形式格式化一个浮点数。Precision确定了要显示的数字的最小个数,缺省值为15。Args的值必须是一个浮点数或Currency值。

f : 用定点小数(Fixed)法形式格式化一个浮点数。Precision确定了要显示的小数点后的数字个数,缺省值为2。Args必须是一个浮点数或Currency值。

g :通用计数法(General)形式格式化一个浮点数。用科学计数法或定点小数法转换为最短的十进制显示格式。Precision确定了要显示的数字的有效数字个数,默认15位。Args的值必须是一个浮点数或Currency值。

n :Number。采用定点小数的形式并且在每三个一组的整数间加上千位符。Args的值必须是一个浮点数或Currency值。

m Money. 格式化一个Currency值。Precision确定了小数点后保留多少位,缺省值由CurrencyDecimals 全局变量提供。货币格式由CurrencyFormat、NegCurrFormat 决定。这个转换由参数CurrencyString、CurrencyFormat、NegCurrFormat、ThousandSeparator、DecimalSeparator和CurrencyDecimals全局变量决定,这些初始值都由操作系统的本地设置提供。通过Windows的区域面板来调整。Args的值必须是一个浮点数或Currency值。

p :Pointer. 把指针格式化为十六进制数。Args必须是一个指针。形式如"XXXX:YYYY", XXXX 是段码,YYYY 为偏移量。

s String. 格式化一个字符或者字串。Precision用来确定至多显示多少个字符。Args必须是一个字符、字串、或Pchar值。

x Hexadecimal. 格式化一个无符号十六进制数。Precision用来确定至少显示多少个字符,不足时补0。Args必须是一个整数。

对于浮点格式,使用小数和千分位符均由全局变量DecimalSeparator和ThousandSeparator获得

可以在格式字符串中设定好Index, width, 和precision 的值,或者使用星号*。例如‘%*:*.*f’,星号表示Args数组的下一个参数将提供这个数值。

这个Format 函数能与其它格式化函数结合,例如:

S := Format('Your total was %s on %s', [FormatFloat('$#,##0.00;;zero', Total),FormatDateTime('mm/dd/yy', Date)]);

每个字串格式化程序都要使用全局变量separators, decimals, date/time formats 等等,有一个重载的带有TformatSettings类型参数的等值函数,这个附加参数提供的格式化信息要强于全局变量,请参看TFormatSettings 注释

function Format(const Format: string; const Args: array of const): string; overload;

function Format(const Format: string; const Args: array of const; const FormatSettings: TFormatSettings): string; overload;

FmtStr 过程采用Format函数相同的形式格式化一个字串,但他并不返回格式化的字串,而是把它存储在Result中

procedure FmtStr(var Result: string; const Format: string; const Args: array of const); overload;

procedure FmtStr(var Result: string; const Format: string; const Args: array of const; const FormatSettings: TFormatSettings); overload;

StrFmt 函数格式化一个字串并把结果保存在Buffer中,必须确认Buffer的长度足够保存结果。Buffer作为返回值返回。为了避免缓冲区益处,请使用StrLFmt函数。

function StrFmt(Buffer, Format: PChar; const Args: array of const): PChar; overload;

function StrFmt(Buffer, Format: PChar; const Args: array of const; const FormatSettings: TFormatSettings): PChar; overload;

StrLFmt 格式一个字串并把结果保存在Buffer中。至多MaxLen个字节将写入Buffer中,而且不包括结尾的#0字节,#0字节通常用来加载一个格式化了的字串后面。返回Buffer值

function StrLFmt(Buffer: PChar; MaxBufLen: Cardinal; Format: PChar; const Args: array of const): PChar; overload;

function StrLFmt(Buffer: PChar; MaxBufLen: Cardinal; Format: PChar;const Args: array of const; const FormatSettings: TFormatSettings): PChar; overload;

{ FormatBuf 格式化一个字串并把结果保存在Buffer中。最多BufLen个字节将被写进Buffer中,包括结尾的#0字节。格式字串的长度由FmtLen给出。在Buffer中结果字串的实际长度被返回。返回值总是小于等于BufLen。

function FormatBuf(var Buffer; BufLen: Cardinal; const Format; FmtLen: Cardinal; const Args: array of const): Cardinal; overload;

function FormatBuf(var Buffer; BufLen: Cardinal; const Format; FmtLen: Cardinal; const Args: array of const; const FormatSettings: TFormatSettings): Cardinal; overload;

WideFormat 格式化WideString字串。作用与Format相同

function WideFormat(const Format: WideString; const Args: array of const): WideString; overload;

function WideFormat(const Format: WideString;const Args: array of const; const FormatSettings: TFormatSettings): WideString; overload;

WideFmtStr 格式化WideString字串,结果返回到Result中,其余与FmtStr相同。

procedure WideFmtStr(var Result: WideString; const Format: WideString; const Args: array of const); overload;

procedure WideFmtStr(var Result: WideString; const Format: WideString; const Args: array of const; const FormatSettings: TFormatSettings); overload;

WideFormatBuf 格式化一个WideString字串并把结果保存在Buffer中。最多BufLen个UNICODE字符将被写进Buffer中,包括结尾的#0字符。格式UNICODE字串的长度由FmtLen给出。在Buffer中结果UNICODE字串的实际长度被返回。返回值总是小于等于BufLen。注意: BufLen, FmtLen 和返回值总是UNICODE字符的长度,不是字节数。 要计算实际的字节数用SizeOf(WideChar)函数

function WideFormatBuf(var Buffer; BufLen: Cardinal; const Format; FmtLen: Cardinal; const Args: array of const): Cardinal; overload;

function WideFormatBuf(var Buffer; BufLen: Cardinal; const Format; FmtLen: Cardinal; const Args: array of const; const FormatSettings: TFormatSettings): Cardinal; overload;

10) 浮点转换程序

每个浮点转换程序都使用全局变量来表示小数位、分离符等格式,也有一个等价的多了一个TformatSettings参数的重载函数。这个附加参数所提供的格式信息要强于全局变量。

FloatToStr 转换浮点数为字串表示。这个转换使用15位通用数字(general number)格式,更详细的描述见FloatToStrF函数

function FloatToStr(Value: Extended): string; overload;

function FloatToStr(Value: Extended; const FormatSettings: TFormatSettings): string; overload;

CurrToStr 转换currency 值为字串格式,使用通用数字(general number)格式,更详细的信息见CurrToStrF 函数

function CurrToStr(Value: Currency): string; overload;

function CurrToStr(Value: Currency; const FormatSettings: TFormatSettings): string; overload;

将会排列一个数值使其落在有效可接受的币值范围之内

常量定义

Windows平台:

MinCurrency: Currency = -922337203685477.5807; //!! overflow?

MaxCurrency: Currency = 922337203685477.5807; //!! overflow?

Linux平台

MinCurrency: Currency =+ 1 //!! overflow?

MaxCurrency: Currency =- 1 //!! overflow?

function FloatToCurr(const Value: Extended): Currency;

function TryFloatToCurr(const Value: Extended; out AResult: Currency): Boolean;

FloatToStrF 转换浮点值为格式化了的字串。Format参数决定这个数字是如何转换的。Precision 参数决定有效数字的个数,Single数是7位,Double数是15位, Extended数是18位。Digits参数依赖选定的Format表达不同的意义。

以下是Format参数可能的值:

ffGeneral – 通用数字格式(General number)。以使字串最短的原则采用定点小数或科学计数法的格式来表示数字:尽可能的使用定点小数计数法,不行的话再用科学计数法。尾部的0都被删除,若没有小数则小数点也被删除。若整数部分小于等于指定的精度(Precision)采用定点格式,超过Precision 或者小于0.00001则采用科学计数法。Digits参数指定指数最小位数(0-4)。

ffExponent – 科学计数法。转换出形如"-d.ddd...E+dddd"的字串。在小数点前总是有一位数字。数字总长度用Precision来限定,指数以"E"开头其后跟一个最多不超过4位的正负数,Digits决定了指数的位数。

ffFixed – 定点格式。转换出形如"-ddd.ddd..."的字串。小数点之前至少有一位数字,小数位数由Digits参数指定(必须介于0-18之间)。若整数部分多于Precision个数位则结果会变为科学计数法表示(ffExponent格式)

ffNumber – 数字格式(Number)。转换出形如"-d,ddd,ddd.ddd..."的字串。ffNumber格式符合ffFixed格式,只是结果字串中包含千分位符。

ffCurrency – 货币格式(Currency)。转换为货币格式的字串。其受全局变量CurrencyString、 CurrencyFormat、NegCurrFormat、ThousandSeparator和DecimalSeparator的影响,这些全局变量的初值由操作系统的本地设置来提供,如Windows下的区域面板,小数位数由Digits决定(0-18)。

对于所有格式符,均由全局变量DecimalSeparator 和ThousandSeparator来决定小数和千分位的分离符。

若给定值是NAN ,则结果字串是'NAN'。若给定值是正无穷则结果字串是'INF'。若给定值是负无穷则结果字串是'-INF'。

function FloatToStrF(Value: Extended; Format: TFloatFormat; Precision, Digits: Integer): string; overload;

function FloatToStrF(Value: Extended; Format: TFloatFormat; Precision, Digits: Integer; const FormatSettings: TFormatSettings): string; overload;

CurrToStrF 转换货币值为其字串形式。其使用方法与FloatToStrF相同,只是其最长精度为19位(小数点后19位小数)

function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer): string; overload;

function CurrToStrF(Value: Currency; Format: TFloatFormat; Digits: Integer; const FormatSettings: TFormatSettings): string; overload;

FloatToText 使用指定的格式、精度、位数转换浮点值为其字符数组形式。这是底层函数。值参数必须是一个Extended 或Currency参数的变量,由ValueType参数指出。结果字串被存储在Buffer中并被返回,Buffer要有足够大。结果字串没有NULL终结符,更详细的描述参看FloatToStrF函数

function FloatToText(BufferArg: PChar; const Value; ValueType: TFloatValue; Format: TFloatFormat; Precision, Digits: Integer): Integer; overload;

function FloatToText(BufferArg: PChar; const Value; ValueType: TFloatValue; Format: TFloatFormat; Precision, Digits: Integer; const FormatSettings: TFormatSettings): Integer; overload;

FormatFloat 使用Format参数来格式化一个浮点值,它包含三部分,用分号隔开,三个部分均是可选的。只有一部分时,格式符应用于所有值;只有两部分时,第一部分应用于正数和0,第二部分应用于负数;三部分都有时,第一部分应用于正数,第二部分应用于负数,第三部分应用于0。如果负数和0值部分是空的,也就是在界定符分号之间没有内容,则用正数值部分代替。如果正数值部分是空的或者全部格式符都是空的,则使用15位有效数字的通用浮点格式(general floating-point),也就是FloatToStrF 调用ffGeneral 格式。如果小数点左边超过18位并且没有指定科学计数法符号也会使用通用浮点格式。每部分的格式标识符描述了一个格式或者直接表示出一个数值,这个数值可以四舍五入到小数点后相应位数。对于0标识符,格式符中小数点两侧的0的个数决定了输出字串的的精度。以下是Format参数:

0 :数字占位符。如果这个位置需要一个数字的话,格式化一个数字;否则显示0。

# :数字占位符。若这位置需要一个数字则格式化成一个数字。

. :小数点(由全局变量DecimalSeparator决定形式)。第一个小数点决定了格式化字串中小数点的位置(其后的均无效)。若格式中没有包含小数点标识符,数值将被四舍五入为整数。

, :千分位符(由全局变量ThousandSeparator决定),整数部分每隔三个数字就使用一次这个千分位符,这个标识符可以被包含在一个格式中的任何部分

E+、E-、e+、e- :科学计数符号。不同的标识符代表不同的指数表现形式。'E+'和'e+'表示对于正指数要显示出正号,'E-'和'e-'则表示省略正指数的正号。

'xx'、"xx" :引号里的字符被原封不动的复制为格式化后的字串(去掉引号之后)。可以在引号里使用其它格式的标识符。

; : 隔开格式化标识符中的整数、负数和0三部分。

以下是一些事例:

Format string 1234 -1234 0.5 0

-----------------------------------------------------------------------

1234 -1234 0.5 0

0 1234 -1234 1 0

0.00 1234.00 -1234.00 0.50 0.00

#.## 1234 -1234 .5

#,##0.00 1,234.00 -1,234.00 0.50 0.00

#,##0.00;(#,##0.00) 1,234.00 (1,234.00) 0.50 0.00

#,##0.00;;Zero 1,234.00 -1,234.00 0.50 Zero

0.000E+00 1.234E+03 -1.234E+03 5.000E-01 0.000E+00

#.###E-0 1.234E3 -1.234E3 5E-1 0E0

----------------------------------------------------------------------- }

function FormatFloat(const Format: string; Value: Extended): string; overload;

function FormatFloat(const Format: string; Value: Extended; const FormatSettings: TFormatSettings): string; overload;

FormatCurr 根据Format参数来格式化Currency值为一个字串。详细的用法见FormatFloat 函数。

function FormatCurr(const Format: string; Value: Currency): string; overload;

function FormatCurr(const Format: string; Value: Currency; const FormatSettings: TFormatSettings): string; overload;

FloatToTextFmt 转换根据Format所确定的格式对一个浮点值进行格式化。Value参数必须是Extended或Currency类型,由ValueType参数指明。结果字串被包存在Buffer中并且返回字符个数。结果字串没有#0终结符。其它参看FormatFloat函数

function FloatToTextFmt(Buf: PChar; const Value; ValueType: TFloatValue; Format: PChar): Integer; overload;

function FloatToTextFmt(Buf: PChar; const Value; ValueType: TFloatValue; Format: PChar; const FormatSettings: TFormatSettings): Integer; overload;

StrToFloat 转换字串为浮点值。这个字串必须是由可选的正负号、小数点、E、e和数字组成。字串的首位空格被忽略。由全局变量DecimalSeparator决定小数点的形式,字串中不许有千分位符和货币符号。字串不是有效的数字形式则产生一个EconvertError异常

function StrToFloat(const S: string): Extended; overload;

function StrToFloat(const S: string; const FormatSettings: TFormatSettings): Extended; overload;

function StrToFloatDef(const S: string; const Default: Extended): Extended; overload;

function StrToFloatDef(const S: string; const Default: Extended; const FormatSettings: TFormatSettings): Extended; overload;

function TryStrToFloat(const S: string; out Value: Extended): Boolean; overload;

function TryStrToFloat(const S: string; out Value: Extended; const FormatSettings: TFormatSettings): Boolean; overload;

function TryStrToFloat(const S: string; out Value: Double): Boolean; overload;

function TryStrToFloat(const S: string; out Value: Double; const FormatSettings: TFormatSettings): Boolean; overload;

function TryStrToFloat(const S: string; out Value: Single): Boolean; overload;

function TryStrToFloat(const S: string; out Value: Single; const FormatSettings: TFormatSettings): Boolean; overload;

StrToCurr 转换字串为Currency类型。其余同StrToFloat函数

function StrToCurr(const S: string): Currency; overload;

function StrToCurr(const S: string; const FormatSettings: TFormatSettings): Currency; overload;

function StrToCurrDef(const S: string; const Default: Currency): Currency; overload;

function StrToCurrDef(const S: string; const Default: Currency; const FormatSettings: TFormatSettings): Currency; overload;

function TryStrToCurr(const S: string; out Value: Currency): Boolean; overload;

function TryStrToCurr(const S: string; out Value: Currency; const FormatSettings: TFormatSettings): Boolean; overload;

TextToFloat 转换Buffer中有Null终结符的字串为浮点数并返回给变量Value。Value参数必须是Extended或Currency类型, 且与ValueType参数相匹配。若转换成功返回True,否则返回False。更详细表述参看StrToFloat函数。

function TextToFloat(Buffer: PChar; var Value; ValueType: TFloatValue): Boolean; overload;

function TextToFloat(Buffer: PChar; var Value; ValueType: TFloatValue; const FormatSettings: TFormatSettings): Boolean; overload;

FloatToDecimal 转换浮点数为十进制格式。是底层的格式化程序,其它格式化函数会调用它,但是一般应用程序很少直接调用它。Value参数必须是Extended或Currency类型,而且要有ValueType参数来指明。对于Extended类型的值,Precision参数指明有效数字的位数,在1-18位之间。对于Currency类型,Precision被忽略,并且默认为19位。Decimals指明整数部分的位数。Precision和Decimals参数一起控制如何舍入。不管数字有多大,为了产生有效的结果,为Decimals参数指定9999。结果被存储在TfloatRec记录类型中。

以下是TfloatRec类型成员:

Exponent – 指数。若数字绝对值小于1则指数为负数。若数字是NAN (非数)则指数为-32768。若数字为INF 或-INF (正负无穷)则指数为32767。

Negative - 若数字为负数则为True 。若为0或正数则是False。

Digits – 包含Null终结符的最多18(Extended)或19 (Currency)位的有效数字。小数点不被存储其中。尾部的0被删除,若结果数字是0、NAN、或INF,Digits则为空但是存有Null终结符。

procedure FloatToDecimal(var Result: TFloatRec; const Value; ValueType: TFloatValue; Precision, Decimals: Integer);

11) 日期/时间支持程序

function DateTimeToTimeStamp(DateTime: TDateTime): TTimeStamp;

function TimeStampToDateTime(const TimeStamp: TTimeStamp): TDateTime;

function MSecsToTimeStamp(MSecs: Comp): TTimeStamp;

function TimeStampToMSecs(const TimeStamp: TTimeStamp): Comp;

EncodeDate 编码日期Year, Month和Day为TdateTime类型值。Year必须介于1-9999之间;Month 必须介于1-12之间;Day必须介于1-N之间,N是指定月的最大数。若超出上述范围则产生一个EconvertError异常。结果值是介于12/30/1899和给定日期之间的天数

function EncodeDate(Year, Month, Day: Word): TDateTime;

{ EncodeTime 编码时间Hour, Min(ute), Sec(ond)和MilliSecond为TdateTime值。Hour必须介于0-23之间;Minute必须介于0-59之间,;Second必须介于0-59之间;MilliSecond必须介于0-999之间。若超出上述范围则产生一个EconvertError异常。结果值是介于0-1(不包括1)之间时间值,这个值指的是占全天时间的比值(总是小于1)。0表示是午夜,0.5表示是中午,0.75表示是下午6:00

function EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime;

代替EncodeDate和EncodeTime函数,但不产生异常。当给定的值有效是返回True,否则返回False。其余完全相同

function TryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): Boolean;

function TryEncodeTime(Hour, Min, Sec, MSec: Word; out Time: TDateTime): Boolean;

DecodeDate 解码日期DateTime值为年Year、月Month、日Day输出。若给定的日期值小于0则输出全为0。

procedure DecodeDate(const DateTime: TDateTime; var Year, Month, Day: Word);

这个函数与DecodeDate功能类似,但是返回更多的信息。DOW是星期。函数返回值指示出Year是否是闰年。

function DecodeDateFully(const DateTime: TDateTime; var Year, Month, Day, DOW: Word): Boolean;

function InternalDecodeDate(const DateTime: TDateTime; var Year, Month, Day, DOW: Word): Boolean; //用于Linux环境

DecodeTime 解码给定时间值DaTime为时Hour、分Min、秒Sec、毫秒MSec输出。

procedure DecodeTime(const DateTime: TDateTime; var Hour, Min, Sec, MSec: Word);

{以下用于MsWindows平台}

DateTimeToSystemTime将Delphi的TdateTime值的日期和时间转换为Win32 API的TsystemTime格式

procedure DateTimeToSystemTime(const DateTime: TDateTime; var SystemTime: TSystemTime);

SystemTimeToDateTime 将Win32 API的日期和时间转换为Delphi的TdateTime格式。

function SystemTimeToDateTime(const SystemTime: TSystemTime): TDateTime;

{$ENDIF}

DayOfWeek 返回给定日期是星期几。结果是介于1-7的整数,对应星期日到星期六。这个函数不是适应ISO 8601的,具体请参看DateUtils单元

function DayOfWeek(const DateTime: TDateTime): Word;

Date 返回当前日期

function Date: TDateTime;

Time 返回当前时间。

function Time: TDateTime;

{以下用于Linux环境}

{ clashes with Time in <X11/Xlib.h>, use GetTime instead }

{$EXTERNALSYM Time}

{$ENDIF}

function GetTime: TDateTime;

Now 返回当前的日期和时间。

function Now: TDateTime;

Currentyear 返回当前日期中的年

function CurrentYear: Word;

IncMonth 给DateTime参数加上NumberOfMonths个月并返回结果。若NumberOfMonths参数为负,将返回N月之前的日期数。若日期数大于该月的最大日期数,则自动设为该月的最大日期数。输入的时间数自动复制进DateTime结果中。

function IncMonth(const DateTime: TDateTime; NumberOfMonths: Integer = 1): TDateTime;

直接用年月日表示的IncMonth函数的优化版本,关于NumberOfMonths可以参照IncMonth函数的注释。

procedure IncAMonth(var Year, Month, Day: Word; NumberOfMonths: Integer = 1);

ReplaceTime 用给定的时间值替换DateTime参数的时间部分,若日期在1900年之前(日期值小于0)就需要调整这个标记。

procedure ReplaceTime(var DateTime: TDateTime; const NewTime: TDateTime);

ReplaceDate用给定的日期值替换DateTime参数的日期部分,若日期为负数就需要调整这个标记。

procedure ReplaceDate(var DateTime: TDateTime; const NewDate: TDateTime);

IsLeapYear 判断Year是否是闰年。

function IsLeapYear(Year: Word): Boolean;

type

PDayTable = ^TDayTable;

TDayTable = array[1..12] of Word;

MonthDays数组能很快地找出每个月的天数。这是一个二维数组,第一位是布尔类型,闰年表示为True,否则为False。第二维表示月份,,范围是1-12。

MonthDays[IsLeapYear(Y), M]

const

MonthDays: array [Boolean] of TDayTable =((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));

每个日期/时间格式化程序都使用separators、decimals等全局变量,同时也有一个等价的具有TformatSettings类型参数的重载函数。这个附加的参数提供了比全局变量强的格式化信息,具体参看TformatSettings参数。

DateToStr 转换给定TdateTime值的日期部分为一个字串。这个转换格式由全局变量ShortDateFormat决定。

function DateToStr(const DateTime: TDateTime): string; overload;

function DateToStr(const DateTime: TDateTime;const FormatSettings: TFormatSettings): string; overload;

TimeToStr 转换给定TdateTime值的时间部分为一个字串 ,使用全局变量LongTimeFormat 来决定格式

function TimeToStr(const DateTime: TDateTime): string; overload;

function TimeToStr(const DateTime: TDateTime; const FormatSettings: TFormatSettings): string; overload;

DateTimeToStr 转换给定日期和时间为字串。结果字串的形式由全局变量ShortDateFormat和LongTimeFormat决定。 给定的值的小数部分不为0则输出字串包含时间部分。

function DateTimeToStr(const DateTime: TDateTime): string; overload;

function DateTimeToStr(const DateTime: TDateTime; const FormatSettings: TFormatSettings): string; overload;

StrToDate 转换字串为日期值。这个字串必须由2或3个数字及分离符组成,分离符的类型由全局变量DateSeparator决定。月日年的次序由全局变量ShortDateFormat决定,可能的形式有月日年m/d/y、日月年d/m/y、和年月日y/m/d。若字串由两个数字组成,则被解释成当年的某个日期(月/日或日/月)。Year必须介于0-99之间并且假定处于当前的世纪中;若给定的字串不是有效的日期则会产生EconvertError异常

function StrToDate(const S: string): TDateTime; overload;

function StrToDate(const S: string; const FormatSettings: TFormatSettings): TDateTime; overload;

function StrToDateDef(const S: string; const Default: TDateTime): TDateTime; overload;

function StrToDateDef(const S: string; const Default: TDateTime; const FormatSettings: TFormatSettings): TDateTime; overload;

function TryStrToDate(const S: string; out Value: TDateTime): Boolean; overload;

function TryStrToDate(const S: string; out Value: TDateTime; const FormatSettings: TFormatSettings): Boolean; overload;

StrToTime 转换字串为时间值。字串必须是由2或3个数字及分离符组成。分离符由全局变量TimeSeparator决定。AM或PM指示符可选,按时、分、秒(可选)顺序。若时间后跟随AM或PM指示符则被假定为12小时格式,否则为24小时格式。若给定字串不是有效的时间格式则产生EconvertError异常。

function StrToTime(const S: string): TDateTime; overload;

function StrToTime(const S: string; const FormatSettings: TFormatSettings): TDateTime; overload;

function StrToTimeDef(const S: string; const Default: TDateTime): TDateTime; overload;

function StrToTimeDef(const S: string; const Default: TDateTime; const FormatSettings: TFormatSettings): TDateTime; overload;

function TryStrToTime(const S: string; out Value: TDateTime): Boolean; overload;

function TryStrToTime(const S: string; out Value: TDateTime; const FormatSettings: TFormatSettings): Boolean; overload;

StrToDateTime 转换字串为日期时间值,字串必须包含一个日期值和可选的尾随其后时间值。字串的日期和时间部分必须遵循由StrToDate和StrToTime函数描述的格式。

function StrToDateTime(const S: string): TDateTime; overload;

function StrToDateTime(const S: string; const FormatSettings: TFormatSettings): TDateTime; overload;

function StrToDateTimeDef(const S: string;const Default: TDateTime): TDateTime; overload;

function StrToDateTimeDef(const S: string; const Default: TDateTime;const FormatSettings: TFormatSettings): TDateTime; overload;

function TryStrToDateTime(const S: string;out Value: TDateTime): Boolean; overload;

function TryStrToDateTime(const S: string; out Value: TDateTime;const FormatSettings: TFormatSettings): Boolean; overload;

FormatDateTime 使用Format参数格式化日期-时间值为一个字串。以下是Format参数指示符:

c 日期采用的格式是全局变量ShortDateFormat指明的,接着是一个空格,再接下来是一个采用全局变量LongTimeFormat表示的时间。若正好是0点,则时间信息省略。

d 显示天时没有前导0 (1-31)。

dd 显示天时有前导0 (01-31)。

ddd 使用全局变量ShortDayNames规定的格式来表示星期几,即缩写词(Sun-Sat)。

dddd 使用全局变量LongDayNames 规定的格式来表示星期几,即全名称(Sunday-Saturday)

ddddd 使用全局变量ShortDateFormat规定的格式来表示日期信息。

dddddd 使用全局变量LongDateFormat规定的格式来表示日期信息。

g 采用短纪年名格式(只对于日本和台湾)。

gg 采用全纪年名格式。

e 在当前的纪年方式下格式化年代信息,同时去掉开头的0(只用于韩国、日本和台湾)。

ee 在当前的纪年方式下格式化年代信息,同时保留开头的0,(只用于日本、韩国和台湾)。

m 格式化月份信息并且去除前导0(1-12)。若m特定符紧紧跟随一个h或hh特定符,则分钟先于月份显示。

mm 格式化月份信息并保留前导0(01-12)。若mm特定符紧紧跟随一个h或hh特定符,则分钟先于月份显示。

mmm 由全局变量ShortMonthNames 规定的格式显示月份,即缩写词 (Jan-Dec)

mmmm 由全局变量LongMonthNames规定的格式显示月份,即全名称 (January-December)

yy 显示两位数的年 (00-99)。

yyyy 显示四位数的年 (0000-9999)。

h 格式化小时信息并且去除前导0 (0-23)。若格式化字串中包含AM/PM标识符时,则采用12小时表示法。

hh 格式化小时信息并且保留前导0 (00-23)。若格式化字串中包含AM/PM标识符时,则采用12小时表示法。

n 显示分钟信息并去除前导0 (0-59)。

nn 显示分钟信息并保留前导0 (00-59)。

s 格式化秒信息并去除前导0 (0-59)。

ss 格式化秒信息并保留前导0 (00-59)。

z 格式化毫秒信息并去除前导0 (0-999)。

zzz 格式化毫秒信息并去除前导0 (000-999)

t 用全局变量ShortTimeFormat规定的格式显示时间信息。

tt 用全局变量LongTimeFormat规定的格式显示时间信息。

am/pm 为前面的h或hh特定符显示为12小时制。从午夜开始到中午之前显示am,在中午及中午以后显示pm。至于am/pm的大小写则与格式化字串中的写法一致

a/p 用法与am/pm一致,只是显示为a或p。

ampm 用法与am/pm一致。只是上午显示的字符是由全局变量TimeAMString规定的(am),下午显示的字符由全局变量TimePMString规定(pm)。

/ 显示由全局变量DateSeparator规定的日期分离符

: 显示由全局变量TimeSeparator规定的时间分离符。

'xx'、"xx" 直接复制引号内的字符(不包括引号)。

格式化字符不区分大小写(除了am/pm和a/p标志)。其它字符被原样复制。若Format是空字串,则缺省的格式为c。以下是一些事例:

S := FormatDateTime('"The meeting is on" dddd, mmmm d, yyyy, ' +'"at" hh:mm AM/PM', StrToDateTime('2/15/95 10:30am'));

S字串显示为:The meeting is on Wednesday, February 15, 1995 at 10:30 AM

function FormatDateTime(const Format: string;DateTime: TDateTime): string; overload;

function FormatDateTime(const Format: string; DateTime: TDateTime;const FormatSettings: TFormatSettings): string; overload;

DateTimeToString 转换DateTime的日期时间为一个字串并通过变量Result返回。其它详细描述参看FormatDateTime函数。

procedure DateTimeToString(var Result: string; const Format: string; DateTime: TDateTime); overload;

procedure DateTimeToString(var Result: string; const Format: string; DateTime: TDateTime; const FormatSettings: TFormatSettings); overload;

FloatToDateTime 转换一个有效的数值为一个合理的日期。

定义常量:

MinDateTime: TDateTime = -657434.0; { 01/01/0100 12:00:00.000 AM }

MaxDateTime: TDateTime = 2958465.99999; { 12/31/9999 11:59:59.999 PM }

function FloatToDateTime(const Value: Extended): TDateTime;

function TryFloatToDateTime(const Value: Extended; out AResult: TDateTime): Boolean;

12) 系统错误信息

返回错误码ErrorCode的文本。应用程序应该报告的是Windows的错误文本而不是代码。Ewin32Error类型在他的异常信息中自动包含了错误消息文本内容,但是EinOutError则没有提供Windows错误码的格式化。

function SysErrorMessage(ErrorCode: Integer): string;

13) 初始化文件支持

在Windows环境中Locale中查找LocaleType的值,并返回结果字串。若Locale或LocaleType无效则返回Default值。GetFormatSettings函数会调用这个函数以载入一些本地化变量。

function GetLocaleStr(Locale, LocaleType: Integer; const Default: string): string; platform;

function GetLocaleChar(Locale, LocaleType: Integer; Default: Char): Char; platform;

GetFormatSettings 从操作系统中获取数值来恢复全部本地变量(日期、时间、数字和货币的格式),一个图形用户界面GUI应用程序会在这些格式化设置被更改后自动调用这个函数(也就是在接收到Wm_WinIniChange消息后)。

GetFormatSettings设置的变量:

CurrencyDecimals:货币值的位数;

CurrencyFormat:正的货币值表示格式;

CurrencyString:标志货币值的符号;

DateSepararor:隔开日期个部分的分隔符;

DecimalSeparator:隔开整数和小数部分的分隔符(小数点);

EraName:亚洲地区使用年代的名字;

EraYearOffsets:亚洲地区使用年代的年份;

ListSeparator:在一个列表中隔开各个项目的分隔符;

LongDayNames:每周各星期的全名表示;

LongMonthNames:每个月份的全名表示;

LongTimeFormat:时间的长格式;

NegCurrFormat:负货币值的表示格式;

ShortDateFormat:日期的简短格式;

ShortDayName:每周各星期的简略表示;

ShortMonthNames:每个月份的简略表示;

ShortTimeFormat:时间的简短格式;

ThousandSeparator:千分位符;

TimeAMString:表示上午的字符串;

TimeP MString:表示下午的字符串;

TimeSeparator:时间的分隔符。

procedure GetFormatSettings;

GetLocaleFormatSettings 用操作系统的值来加载到指定区域(LCID)的本地变量(date, time, number,currency formats)中。 这个值被储存在FormatSettings记录中

{以下用于MsWindows平台}

procedure GetLocaleFormatSettings(LCID: Integer; var FormatSettings: TFormatSettings);

{$ENDIF}

14) 异常处理程序

{以下用于Linux环境}

InquireSignal is used to determine the state of an OS signal handler. Pass it one of the RTL_SIG* constants, and it will return a TsignalState which will tell you if the signal has been hooked, not hooked, or overriden by some other module. You can use this function to determine if some other module has hijacked your signal handlers, should you wish to reinstall your own. This is a risky proposition under Linux, and is only recommended as a last resort. Do not pass RTL_SIGDEFAULT to this function.

function InquireSignal(RtlSigNum: Integer): TSignalState;

AbandonSignalHandler tells the RTL to leave a signal handler in place, even if we believe that we hooked it at startup time. Once you have called AbandonSignalHandler with a specific signal number, neither UnhookSignal nor the RTL will restore any previous signal handler under any condition.

procedure AbandonSignalHandler(RtlSigNum: Integer);

HookSignal is used to hook individual signals, or an RTL-defined default set of signals. It does not test whether a signal has already been hooked, so it should be used in conjunction with InquireSignal. It is exposed to enable users to hook signals in standalone libraries, or in the event that an external module hijacks the RTL installed signal handlers. Pass RTL_SIGDEFAULT if you want to hook all the signals that the RTL normally hooks at startup time.

procedure HookSignal(RtlSigNum: Integer);

UnhookSignal is used to remove signal handlers installed by HookSignal. It can remove individual signal handlers, or the RTL-defined default set of signals. If OnlyIfHooked is True, then we will only unhook the signal if the signal handler has been hooked, and has not since been overriden by some foreign handler.

procedure UnhookSignal(RtlSigNum: Integer; OnlyIfHooked: Boolean = True);

HookOSExceptions 用于线程内部的支持,你自己不能调用这个过程。

procedure HookOSExceptions;

MapSignal is used internally as well. It maps a signal and associated context to an internal value that represents the type of Exception class to raise.

function MapSignal(SigNum: Integer; Context: PSigContext): LongWord;

SignalConverter 被用于内部适当的控制FPU 并且适当的产生一个外部OS异常对象。你自己不能调用这个过程。

procedure SignalConverter(ExceptionEIP: LongWord; FaultAddr: LongWord; ErrorCode: LongWord);

看看下面的线程变量声明的注释。只能使用以下过程和函数来访问线程变量,因为你不能越过包来使用线程变量。

procedure SetSafeCallExceptionMsg(const Msg: String);

procedure SetSafeCallExceptionAddr(Addr: Pointer);

function GetSafeCallExceptionMsg: String;

function GetSafeCallExceptionAddr: Pointer;

HookOSExceptionsProc 只限于内部使用而不能在常规场合使用,并且不能不断的设置这个变量

变量声明:

HookOSExceptionsProc: procedure = nil platform deprecated;

LoadLibrary / FreeLibrary are defined here only for convenience. On Linux, they map directly to dlopen / dlclose. Note that module loading semantics on Linux are not identical to Windows.

function LoadLibrary(ModuleName: PChar): HMODULE;

function FreeLibrary(Module: HMODULE): LongBool;

GetProcAddress does what it implies. It performs the same function as the like named function under Windows. dlsym does not quite have the same sematics as GetProcAddress as it will return the address of a symbol in another module if it was not found in the given HMODULE. This function will verify that the 'Proc' is actually found within the 'Module', and if not returns nil

function GetProcAddress(Module: HMODULE; Proc: PChar): Pointer;

Given a module name, this function will return the module handle. There is no direct equivalent in Linux so this function provides that capability. Also note, this function is specific to glibc.

function GetModuleHandle(ModuleName: PChar): HMODULE;

This function works just like GetModuleHandle, except it will look for a module that matches the given base package name. For example, given the base package name 'package', the actual module name is, by default, 'bplpackage.so'. This function will search for the string 'package' within the module name.

function GetPackageModuleHandle(PackageName: PChar): HMODULE;

{$ENDIF}

暂停程序运行milliseconds 毫秒,milliseconds参数在Windows中指的是毫秒,在Linux中则指的是秒。在Windows中这个函数直接调用系统API函数。

procedure Sleep(milliseconds: Cardinal);{$IFDEF MSWINDOWS} stdcall; {$ENDIF}

{以下用于MsWindows平台}

(*$EXTERNALSYM Sleep*)

{$ENDIF}

function GetModuleName(Module: HMODULE): string;

为了一个异常而格式化一个字符串。把异常对象和地址作为开始的两个参数。字符串缓冲区和它的大小是接下来的两个参数。函数返回格式化后的字符串的长度。异常信息包含了模块名、异常地址、异常类型名以及异常消息(若异常对象是从Exception中继承而来的)。

function ExceptionErrorMessage(ExceptObject: TObject; ExceptAddr: Pointer; Buffer: PChar; Size: Integer): Integer;

显示一个异常消息。在控制台应用程序中,异常消息通常写入Output文件中,消息则显示在一个对话框中。至于对话框的文本内容则通过调用ExceptionErrorMessage来获得。

procedure ShowException(ExceptObject: TObject; ExceptAddr: Pointer);

报告一个Eabort异常。GUI应用程序将忽略掉这个异常,因此可以调用Abort过程来报告一个用户看不见的异常。

procedure Abort;

报告一个EOutOfMemory异常。SysUtils单元会预先分配一个单独的EOutOfMemory对象,这里也使用到了OutOfMemory过程。免得想要分配空间给一个新的异常对象时却发现没有可分配的空间了。当你正在写一个内存管理器时,不需要调用OutOfMemory过程来报告一个错误,相应的,只用确认内存分配或者重分配函数返回nil,其它的工作Delphi会处理。

procedure OutOfMemoryError;

调用Windows的API函数MessageBeep(0),它播放的是系统声音。

procedure Beep;

15) MBCS 函数

LeadBytes 变量定义多字节字符集中(日本、中国等)字符的用于指示的前导字节,应根据本地代码表来设置这个变量。对于西文国家来说,这个设置总是空的。

变量声明

LeadBytes: set of Char = [];

ByteType 返回字串S中第Index个位置上的字节类型。对于西文国家总是返回mbSingleByte。远东多字节地区可能返回mbLeadByte,指出这是多字节字符的首字节。而返回值mbTrailByte,则指出是首字节之后的字节。首字节之后可能有一个或多个字节跟随,这取决于本地的字符集编码和操作系统平台。Index参数总是有效的,这意味着若其越界则结果变得不可预知。

function ByteType(const S: string; Index: Integer): TMbcsByteType;

StrByteType 与ByteType函数类似,只是用于有Null终结符的Pchar字串。

function StrByteType(Str: PChar; Index: Cardinal): TMbcsByteType;

ByteToCharLen 返回MBCS字串的字符数目,扫描长度为MaxLen个字节。在多字节字符集中,字符的长度小于字节的长度。

function ByteToCharLen(const S: string; MaxLen: Integer): Integer;

CharToByteLen 返回MBCS字串S的字节长度,扫描MaxLen个字符。

function CharToByteLen(const S: string; MaxLen: Integer): Integer;

ByteToCharIndex 返回MBCS字串指定的第Index个字节处所对应的字符索引值,索引以1开始。若Index超出范围((Index <= 0)或(Index > Length(S)))则返回0。

function ByteToCharIndex(const S: string; Index: Integer): Integer;

CharToByteIndex返回MBCS字串指定的第Index个字符处所对应的字节索引值,索引以1开始。若Index超出范围((Index <= 0)或(Index > Length(S))或(Result可能> Length(S)))则返回0。

function CharToByteIndex(const S: string; Index: Integer): Integer;

StrCharLength 返回Str中第一个字符的字节数。在Windows中,多字节字符的长度是2个字节。在Linux中,多字节字符长度是6个字节(UTF-8)。

function StrCharLength(const Str: PChar): Integer;

StrNextChar 返回Str字串指针位置后面的字符指针,即下一个字符的指针。

function StrNextChar(const Str: PChar): PChar;

CharLength 返回字串S中第Index字节处的字符的字节数

function CharLength(const S: String; Index: Integer): Integer;

NextCharIndex 返回字串S第Index字符后面的字符的首字节的索引值,即下一个字符的索引值。

function NextCharIndex(const S: String; Index: Integer): Integer;

IsPathDelimiter 若在字节S[Index]处的字符是一个路径分隔符('/' 或'/')则返回True,并且不是MBCS头或尾字节。

function IsPathDelimiter(const S: string; Index: Integer): Boolean;

IsDelimiter 若在字节S[Index]出于任何分隔符相匹配则返回True,并且不是MBCS头或尾字节。字串S可以包含多字节字符,分隔符一定是单字节字符。

function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;

IncludeTrailingPathDelimiter 返回一个结尾有路径分隔符PathDelimiter(/或/)的路径,这函数是MBCS才有的。

function IncludeTrailingPathDelimiter(const S: string): string;

IncludeTrailingBackslash 是函数IncludeTrailingPathDelimiter的旧名称。

function IncludeTrailingBackslash(const S: string): string; platform;

ExcludeTrailingPathDelimiter返回一个结尾没有有路径分隔符PathDelimiter(/或/)的路径,这函数是MBCS才有的。

function ExcludeTrailingPathDelimiter(const S: string): string;

ExcludeTrailingBackslash 是函数ExcludeTrailingPathDelimiter的旧名称

function ExcludeTrailingBackslash(const S: string): string; platform;

LastDelimiter 在整个字串S中匹配任何一个Delimiters分隔符(除了NULL(#0)),返回最右侧的分隔符的字节索引值,即最后的那个分隔符的字节索引。S可以包含多字节字符,分隔符一定是单字节的并且不是Null字符。例如:LastDelimiter('/.:', 'c:/filename.ext') 返回值是12.

function LastDelimiter(const Delimiters, S: string): Integer;

AnsiCompareFileName文件名的比较。支持Windows下的全长度日本字符(Zenkaku)的DOS文件名,这种情况下,ASII字符将占用两个字节。在Windows非MBCS下,此函数与AnsiCompareText (区分大小写)相同。在Linux下,与AnsiCompareStr (区分大小写)相同。对于普通文件名比较,应当使用函数AnsiCompareText。

function AnsiCompareFileName(const S1, S2: string): Integer;

function SameFileName(const S1, S2: string): Boolean;

AnsiLowerCaseFileName文件名转换为小写。支持在Windows下的全长度日本字符(Zenkaku)的DOS文件名,这种情况下,ASII字符将占用两个字节。在非MBCS下,此函数与AnsiLowerCase相同。

function AnsiLowerCaseFileName(const S: string): string;

AnsiUpperCaseFileName 文件名转换为大写。支持在Windows下的全长度日本字符(Zenkaku)的DOS文件名,这种情况下,ASII字符将占用两个字节。在非MBCS下,此函数与AnsiUpperCase相同。

function AnsiUpperCaseFileName(const S: string): string;

AnsiPos: 与Pos函数功能一样只是支持MBCS。

function AnsiPos(const Substr, S: string): Integer;

AnsiStrPos: 与StrPos函数功能一样只是支持MBCS。

function AnsiStrPos(Str, SubStr: PChar): PChar;

AnsiStrRScan: 与StrRScan函数功能一样只是支持MBCS。

function AnsiStrRScan(Str: PChar; Chr: Char): PChar;

AnsiStrScan: 与StrScan函数功能一样只是支持MBCS。

function AnsiStrScan(Str: PChar; Chr: Char): PChar;

StringReplace 在字串S中,用newpattern 字串替换其中的oldpattern字串(区分大小写)。S可以包含多字节字符。Flags属性是rfReplaceAll则替换所有的oldpattern。若是rfIgnoreCase则比较时忽略大小写

type

TReplaceFlags = set of (rfReplaceAll, rfIgnoreCase);

function StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;

WrapText 在字串Line中扫描字符BreakChars;并且在最后的BreakChar位置处(在MaxCol之前)插入字串BreakStr,但是不能插入到引号串内(包括单引号和双引号)。

function WrapText(const Line, BreakStr: string; const BreakChars: TSysCharSet; MaxCol: Integer): string; overload;

function WrapText(const Line: string; MaxCol: Integer = 45): string; overload;

FindCmdLineSwitch 决定Switch参数怎样作为命令行参数传递到应用程序。witchChars参数指出哪个字符为命令分隔符(通常是-/)。The IgnoreCase 参数为False则表明Switch参数必须完全相同(区分大小写),否则忽略大小写

常量定义:

SwitchChars = ['/','-']; //Windows下

SwitchChars = ['-']; //Linux下

function FindCmdLineSwitch(const Switch: string; const Chars: TSysCharSet; IgnoreCase: Boolean): Boolean; overload;

这是函数FindCmdLineSwitch的简化版。有效的命令行开关字符在不同的平台下会改变,例如在Linux下'/' 不能被作为开关字符因为他是一个路径分隔符。这个函数Switch参数区分大小写(相当于前的函数的IgnoreCase属性为False)。

function FindCmdLineSwitch(const Switch: string): Boolean; overload;

这个SwitchChars定义与上面相同

function FindCmdLineSwitch(const Switch: string; IgnoreCase: Boolean): Boolean; overload;

FreeAndNil 释放Obj对象实例并且设置其变量为Nil。

procedure FreeAndNil(var Obj);

16) 接口支持程序

function Supports(const Instance: IInterface; const IID: TGUID; out Intf): Boolean; overload;

function Supports(const Instance: TObject; const IID: TGUID; out Intf): Boolean; overload;

function Supports(const Instance: IInterface; const IID: TGUID): Boolean; overload;

function Supports(const Instance: TObject; const IID: TGUID): Boolean; overload;

function Supports(const AClass: TClass; const IID: TGUID): Boolean; overload;

function CreateGUID(out Guid: TGUID): HResult;

function CreateGUID(out Guid: TGUID): HResult; stdcall; //Windows

function StringToGUID(const S: string): TGUID;

function GUIDToString(const GUID: TGUID): string;

function IsEqualGUID(const guid1, guid2: TGUID): Boolean;

{以下用于MsWindows平台}

stdcall; {$EXTERNALSYM IsEqualGUID}

{$ENDIF}

17) 包支持程序

包信息标记

常量定义

pfNeverBuild = $00000001; //外部建立

pfDesignOnly = $00000002; //设计时刻包程序

pfRunOnly = $00000004; //运行时包程序

pfIgnoreDupUnits = $00000008; //不检查是否有重复的单元

pfModuleTypeMask = $C0000000; //模块类型的掩码

pfExeModule = $00000000; //可执行程序(在Delphi5中是$C0000000)

pfPackageModule = $40000000; //包程序DLL

pfProducerMask = $0C000000; //建立本包程序的编译器的标志掩码

pfV3Produced = $00000000; //Delphi3或者Builder3

pfProducerUndefined = $04000000; //未知的编译器

pfBCB4Produced = $08000000; //C++Builder4或者更新的版本

pfDelphi4Produced = $0C000000; //Delphi4或者更新的版本

pfLibraryModule = $80000000; //其他的DLL

单元信息标记

常量定义

ufMainUnit = $01; //保程序或工程的主要单元

ufPackageUnit = $02; //包程序源单元(.dpk文件)

ufWeakUnit = $04; //单元是弱连接的

ufOrgWeakUnit = $08; //在其自身定义包程序中被弱连接的单元

ufImplicitUnit = $10; //单元隐含的连接

ufWeakPackageUnit = ufPackageUnit or ufWeakUnit;

Var PkgLoadingMode: Integer = RTLD_LAZY; //Linux

回收过程类型给GetPackageInfo函数使用。Name是包元素的实际名字,若IsUnit是True则Name是被包含单元的名字,若是False则是必须的包。Param被传送到函数GetPackageInfo。

类型(type)定义:

TNameType = (ntContainsUnit, ntRequiresPackage, ntDcpBpiName);

TPackageInfoProc = procedure (const Name: string; NameType: TNameType; Flags: Byte; Param: Pointer);

LoadPackage 加载一个包程序DLL,检查是否有重复的单元,并且调用所有被包含单元的初始化块(initialization)部分。返回最新载入DLL的模块句柄。若Name指明的程序不正确,则产生一个EpackageError异常。

function LoadPackage(const Name: string): HMODULE;

UnloadPackage 与LoadPackage函数相反,调用所有被包含单元的结束化块(finalization)卸载包DLL。必须保证程序中不再有不安全的指针,例如对类的引用,对事件的引用或者是对包程序中方法的引用。

procedure UnloadPackage(Module: HMODULE);

GetPackageInfo 访问给定Module包的信息表并且列举所有的被包含单元和必须的包。此过程为一个已载入模块(程序、库函数或者是包程序)及相关包程序的所有单元调用InfoProc方法。Param是一个不透明的指针,可以直接传递给InfoProc。此过程会把包程序标志设置为Flags,这些标志如上所示。若模块不是Delphi或者C++Builder模块,则产生一个GetPackageInfo异常。

procedure GetPackageInfo(Module: HMODULE; Param: Pointer; var Flags: Integer; InfoProc: TPackageInfoProc);

GetPackageDescription 返回由ModuleName指定的模块的描述资源,若描述资源不存在,则返回空串。若文件不存在或其它错误则产生一个EPackageError异常。描述字串通过$D或者$Description编译指示字来标记,并且会被编译存储为一个名叫DESCRIPTION的RCDATA资源。

function GetPackageDescription(ModuleName: PChar): string;

InitializePackage 确认并初始化给定的包DLL。若包没有初始化部分,则会报告一个异常。LoadfPackage函数会调用这个过程,因此没有理由自己调用这个过程。

procedure InitializePackage(Module: HMODULE);

FinalizePackage 结束给定的包DLL。若包没有结束化部分,则报告一个异常。UnloadPackage函数会调用这个过程,因此没有理由自己调用这个过程。

procedure FinalizePackage(Module: HMODULE);

RaiseLastOSError 用GetLastError函数找回在调用OS或系统库函数时发生的最近一次的错误码。若其返回一个错误码,则其将会产生一个由错误码和系统提供的消息组合而成的EOSError异常。

procedure RaiseLastOSError;

{以下用于MsWindows平台}

procedure RaiseLastWin32Error; deprecated; // 用RaiseLastOSError

Win32Check 用来检查Win32 API函数的返回值,返回一个布尔值表明WIN32 API函数能否正常返回。若WIN32 API函数返回False,则Win32Check调用RaiseLastOSError来产生一个异常。若WIN32 API函数返回True,则Win32Check返回True。

function Win32Check(RetVal: BOOL): BOOL; platform;

{$ENDIF}

18) 终止过程支持

类型定义(type):

TTerminateProc = function: Boolean;

Call AddTerminateProc 添加一个终止过程到系统终止过程列表中。Delphi在应用程序终止前调用终止过程列表中所有的函数。若应用程序安全终止则用户自定义的TermProc函数将返回True,否则返回False。只要终止过程列表中任何函数返回False,应用程序就不会终止。

procedure AddTerminateProc(TermProc: TTerminateProc);

CallTerminateProcs 当一个应用程序正要终止时此函数被VCL调用。如果系统的终止过程列表中的所有函数都返回True,此函数就返回True。 这个函数只能由Delphi来调用,不能被直接调用。

function CallTerminateProcs: Boolean;

function GDAL: LongWord;

procedure RCS;

procedure RPR;

HexDisplayPrefix 变量表示用来作为十六进制数前缀的字符。对于Pascal是$,对于C++是0x。这个字符只用于显示,不影响字串-整数转换程序。

var

HexDisplayPrefix: string = '$';

{以下用于MsWindows平台}

Win95下的Win32 API函数GetDiskFreeSpace不支持超过2GB的磁盘分区。Win NT4.0和Win95 OSR2中新的Win32 函数GetDiskFreeSpaceEx支持超过2GB的分区。GetDiskFreeSpaceEx 函数指针变量在启动时被初始化为指向当前的OS API函数(若系统中有此函数),或者是指向内部的Delphi函数(系统中没有)。当运行在Win95 pre-OSR2以下版本时,此函数的结果仍局限于2GB范围, 指示不用担心你自己来写API函数了。

var

GetDiskFreeSpaceEx: function (Directory: PChar; var FreeAvailable, TotalSpace: TLargeInteger; TotalFree: PLargeInteger): Bool stdcall = nil;

SafeLoadLibrary 安全调用LoadLibrary, 即使被请求的文件不能被加载也不会弹出Win32错误消息对话框。SafeLoadLibrary也会越过LoadLibrary保护当前FPU控制字 (precision, exception masks) (防止万一你在DLL的初始化中载入Hammers FPU控制字,也会像MS DLLs一样执行)

function SafeLoadLibrary(const FileName: string; ErrorMode: UINT = SEM_NOOPENFILEERRORBOX): HMODULE;

{$ENDIF}

{以下用于Linux环境}

SafeLoadLibrary 调用LoadLibrary,越过LoadLibrary保护当前FPU控制字 (精度、异常标志) (在共享对象中防止万一你在它的初始化中载入Hammers FPU控制字,也会像MS DLLs一样执行)

function SafeLoadLibrary(const FileName: string; Dummy: LongWord = 0): HMODULE;

{$ENDIF}

19) 线程同步

IReadWriteSync 是一个为普通读写同步的抽象接口。一些执行程序可以允许同时发生读取,而写总是被禁止。最坏的事情是类表现到同样一个TRTLCriticalSection ,也就是读和写锁定阻碍全部其它线程。

type

IReadWriteSync = interface

['{7B108C52-1D8F-4CDB-9CDF-57E071193D3F}']

procedure BeginRead;

procedure EndRead;

function BeginWrite: Boolean;

procedure EndWrite;

end;

TSimpleRWSync = class(TInterfacedObject, IReadWriteSync)

private

FLock: TRTLCriticalSection;

public

constructor Create;

destructor Destroy; override;

procedure BeginRead;

procedure EndRead;

function BeginWrite: Boolean;

procedure EndWrite;

end;

TThreadLocalCounter

{

This class implements a lightweight non-blocking thread local storage

mechanism specifically built for tracking per-thread recursion counts

in TMultiReadExclusiveWriteSynchronizer. This class is intended for

Delphi RTL internal use only. In the future it may be generalized

and "hardened" for general application use, but until then leave it alone.

Rules of Use:

The tls object must be opened to gain access to the thread-specific data

structure. If a threadinfo block does not exist for the current thread,

Open will allocate one. Every call to Open must be matched with a call

to Close. The pointer returned by Open is invalid after the matching call

to Close (or Delete).

The thread info structure is unique to each thread. Once you have it, it's

yours. You don't need to guard against concurrent access to the thread

data by multiple threads - your thread is the only thread that will ever

have access to the structure that Open returns. The thread info structure

is allocated and owned by the tls object. If you put allocated pointers

in the thread info make sure you free them before you delete the threadinfo

node.

When thread data is no longer needed, call the Delete method on the pointer.

This must be done between calls to Open and Close. You should not use the

thread data after calling Delete.

Important: Do not keep the tls object open for long periods of time.

In particular, be careful not to wait on a thread synchronization event or

critical section while you have the tls object open. It's much better to

open and close the tls object before and after the blocking event than to

leave the tls object open while waiting.

Implementation Notes:

The main purpose of this storage class is to provide thread-local storage

without using limited / problematic OS tls slots and without requiring

expensive blocking thread synchronization. This class performs no

blocking waits or spin loops! (except for memory allocation)

Thread info is kept in linked lists to facilitate non-blocking threading

techniques. A hash table indexed by a hash of the current thread ID

reduces linear search times.

When a node is deleted, its thread ID is stripped and its Active field is

set to zero, meaning it is available to be recycled for other threads.

Nodes are never removed from the live list or freed while the class is in

use. All nodes are freed when the class is destroyed.

Nodes are only inserted at the front of the list (each list in the hash table).

The linked list management relies heavily on InterlockedExchange to perform

atomic node pointer replacements. There are brief windows of time where

the linked list may be circular while a two-step insertion takes place.

During that brief window, other threads traversing the lists may see

the same node more than once more than once. (pun!) This is fine for what this

implementation needs. Don't do anything silly like try to count the

nodes during a traversal.

}

type

PThreadInfo = ^TThreadInfo;

TThreadInfo = record

Next: PThreadInfo;

ThreadID: Cardinal;

Active: Integer;

RecursionCount: Cardinal;

end;

TThreadLocalCounter = class

private

FHashTable: array [0..15] of PThreadInfo;

function HashIndex: Byte;

function Recycle: PThreadInfo;

public

destructor Destroy; override;

procedure Open(var Thread: PThreadInfo);

procedure Delete(var Thread: PThreadInfo);

procedure Close(var Thread: PThreadInfo);

end;

{以下用于MsWindows平台}

{ TMultiReadExclusiveWriteSynchronizer minimizes thread serialization to gain

read access to a resource shared among threads while still providing complete

exclusivity to callers needing write access to the shared resource.

(multithread shared reads, single thread exclusive write)

Read locks are allowed while owning a write lock.

Read locks can be promoted to write locks within the same thread.

(BeginRead, BeginWrite, EndWrite, EndRead)

Note: Other threads have an opportunity to modify the protected resource

when you call BeginWrite before you are granted the write lock, even

if you already have a read lock open. Best policy is not to retain

any info about the protected resource (such as count or size) across a

write lock. Always reacquire samples of the protected resource after

acquiring or releasing a write lock.

The function result of BeginWrite indicates whether another thread got

the write lock while the current thread was waiting for the write lock.

Return value of True means that the write lock was acquired without

any intervening modifications by other threads. Return value of False

means another thread got the write lock while you were waiting, so the

resource protected by the MREWS object should be considered modified.

Any samples of the protected resource should be discarded.

In general, it's better to just always reacquire samples of the protected

resource after obtaining a write lock. The boolean result of BeginWrite

and the RevisionLevel property help cases where reacquiring the samples

is computationally expensive or time consuming.

RevisionLevel changes each time a write lock is granted. You can test

RevisionLevel for equality with a previously sampled value of the property

to determine if a write lock has been granted, implying that the protected

resource may be changed from its state when the original RevisionLevel

value was sampled. Do not rely on the sequentiality of the current

RevisionLevel implementation (it will wrap around to zero when it tops out).

Do not perform greater than / less than comparisons on RevisionLevel values.

RevisionLevel indicates only the stability of the protected resource since

your original sample. It should not be used to calculate how many

revisions have been made.

}

type

TMultiReadExclusiveWriteSynchronizer = class(TInterfacedObject, IReadWriteSync)

private

FSentinel: Integer;

FReadSignal: THandle;

FWriteSignal: THandle;

FWaitRecycle: Cardinal;

FWriteRecursionCount: Cardinal;

tls: TThreadLocalCounter;

FWriterID: Cardinal;

FRevisionLevel: Cardinal;

procedure BlockReaders;

procedure UnblockReaders;

procedure UnblockOneWriter;

procedure WaitForReadSignal;

procedure WaitForWriteSignal;

{$IFDEF DEBUG_MREWS}

procedure Debug(const Msg: string);

{$ENDIF}

public

constructor Create;

destructor Destroy; override;

procedure BeginRead;

procedure EndRead;

function BeginWrite: Boolean;

procedure EndWrite;

property RevisionLevel: Cardinal read FRevisionLevel;

end;

{$ELSE}

type

TMultiReadExclusiveWriteSynchronizer = TSimpleRWSync;

{$ENDIF}

Type

TMREWSync = TMultiReadExclusiveWriteSynchronizer; // 简易格式

function GetEnvironmentVariable(const Name: string): string; overload;

{以下用于Linux环境}

function InterlockedIncrement(var I: Integer): Integer;

function InterlockedDecrement(var I: Integer): Integer;

function InterlockedExchange(var A: Integer; B: Integer): Integer;

function InterlockedExchangeAdd(var A: Integer; B: Integer): Integer;

{$ENDIF}

你可能感兴趣的:(util)