Stream对象又称流式对象
posted @ 2011-09-22 09:27 delphi初学者 阅读(76) 评论(0) 编辑
Fillchar
[例1]:Fillchar通常用来给数据赋初值。
var a:array [1..10] of arrtype;
执行fillchar(a,sizeof(a),0);
当arrtype为
1.real(其他实数类型差不多) 使得a中的元素全部成为0.0
2.integer(byte,word,longint,shortint都相同) 全部为0
3.boolean 全部为false
4.char 全部为#0
这里使用了函数sizeof(a),其功能是返回变量a所占的总字节数,如上例返回:
当arrtype为
1.real sizeof(a)的值为60(每个元素占6个字节,10个元素共占60个字节)
single sizeof(a)的值为40(每个元素占4个字节,10个元素共占40个字节)
double sizeof(a)的值为80(每个元素占8个字节,10个元素共占80个字节)
extended sizeof(a)的值为100(每个元素占10个字节,10个元素共占100个字节)
comp sizeof(a)的值为80(每个元素占8个字节,10个元素共占80个字节)
2.integer(word) sizeof(a)的值为20 (每个元素占2个字节,10个元素共占20个字节)
3.byte (shortint) sizeof(a)的值为10 (每个元素占1个字节,10个元素共占10个字节)
4.longint sizeof(a)的值为40 (每个元素占4个字节,10个元素共占40个字节)
5.boolean sizeof(a)的值为10(每个元素占1个字节,10个元素共占10个字节)
6.char sizeof(a)的值为10 (每个元素占1个字节,10个元素共占10个字节)
所以例1的结果就是将数组a的所有元素(全部字节)用0来填充,要注意对不同类型的数据而言,对“0”的“解释”是截然不同的!对整型或实型量来 讲,所有字节均为0,则该量也为0;对boolean型量(一个字节)来讲,0表示false(非0数表示true),则该量为false;对char型 量(一个字节)来讲,0表示ASCII码值为0的字符,则该量为#0。
[例2]:将上例中的fillchar(a,sizeof(a),0)改为 fillchar(a,sizeof(a),1),结果如何呢?
执行fillchar(a,size(a),1);
当arrtype为
1.boolean 全部为true(1是非0值,表示true)
2.char 全部为#1
3.byte,shortint 每个元素是1字节量,全部为1
4.integer,word 每个元素是2字节量,全部为(257)10。这是因为
在一个integer或word 型变量中,它的高、低两个字节均用1来填充(将10进制数1转化为二进制数00000001),结果为:
高字节 低字节
15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 1 | 0 0 0 0 0 0 0 1
显然,得到的量就是(257)10=(0000000100000001)2。
如果,执行的是fillchar(a,size(a),171),结果又是怎样的?
因为(171)10=(10101011)2,所以,填充后为:
高字节 低字节
15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
1 0 1 0 1 0 1 1 | 1 0 1 0 1 0 1 1
对于integer类型的量,其值为(-21589)10,这是因为integer类型的数据是用补码表示的有符号数,最高位是符号位,0表示 正,1表示负,由于本数是负数,补码为1010101110101011,则反码为1010101110101010,原码为 1101010001010101,其值为-(214+212+210+26+24+22+1)10=-(21589)10;对于word类型的量,其值 为(43947)10,这是因为word类型的数据是用原码表示的无符号数(非负数),原码为1010101110101011,其值为(215+213 +211+29+28+27+25+23+21+1)10=(43947)10;
5.longint 每个元素是4字节量,执行fillchar(a,size(a),1)后,全部为(16843009)10。这是因为,对于每个元素来讲,用1填充后变为:
最高字节 次高字节
31 30 29 28 27 26 25 24 | 23 22 21 20 19 18 17 16
0 0 0 0 0 0 0 1 | 0 0 0 0 0 0 0 1
次低字节 最低字节
15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 1 | 0 0 0 0 0 0 0 1
longint类型的数据是用补码表示的有符号数,最高位是符号位,0表示正,1表示负,由于本数是正数,故补码、反码及原码均为 00000001000000010000000100000001,其值为(224+216+28+1)10=( 16843009)10;
如果,执行的是fillchar(a,size(a),255),结果又是怎样的?
由于(255)10=(11111111)2,故填充后,补码为11111111111111111111111111111111,它是负数, 则其反码为11111111111111111111111111111110,原码为 10000000000000000000000000000001,其值为-1
6.single 每个元素是4字节量,全部为2.36942782761724E-0038,这是因为,对于每个元素来讲,用1填充后的结果与longint类型的二进制码完全相同,但是, single类型对此数据的“解释”却完全不同:
A.最高位(第31位)是整个数的符号位,0为正, 1为负;
B.接着的8位(第30位至第23位)是用移码表示的阶码;
C.后面的23位(第22至第0位)表示尾数;
D.单精度量的值为:±2实际指数*实际尾数
①、若阶码=00000000,则实际指数=-126,实际尾数=(0.???????????????????????)2,其中的?代表相应位置上的二进制码(0或1);显然,在?全为0时, 这个单精度量的值为0;
②、若阶码大于00000000且小于11111111,则实际指数=阶码-(127)10=阶码-01111111,实际尾数=(1.???????????????????????)2
③、INF(无穷大)若阶码=11111111,尾数全0,则已达上界,被作为无穷大
④、浮点运算错误:若阶码=11111111,尾数在(00000000000000000000000, 10000000000000000000000)之间。
⑤、NAN(非数:Not A Number)若阶码=11111111,尾数在[10000000000000000000000, 11111111111111111111111]之间
下面,我们来分析二进制码为00000001000000010000000100000001的单精度数(single类型)的值是多少。①最 高位为0,表示正数;②阶码为00000010,换成10进制数为2,则实际指数=2-127=-125,③尾数为 00000010000000100000001,实际尾数=1. 00000010000000100000001, 换成10进制数为1+2-7+2-15+2-23=1.00784313678741455078125, ④此单精度数的值是+2-125*1.00784313678741455078125≈2.36942782761724e-38
7.其他实数类型就不一一列举了。
8.对于集合类型 若arrtype=set of '#'..'z'; 执行fillchar(a,sizeof(a),0)后的结果:a全为空集;sizeof(a)返回120。为什么sizeof(a)的值为120?原 来,对集合类型来讲,由于元素范围事先必须给定(如'#'..'z'),每个元素是否存在于某集合中,只需用0或1记下即可,用0表示该元素不属于某集 合,用1表示该元素属于某集合,即只用1个二进制位就可表示1个元素是否属于某集合,那么只要我们按元素的序号顺序记下一串二进制代码,就可以标记所有范 围内的元素是否属于某集合了。但这里有一个问题:数据的存储通常是以字节为单位进行的,不是直接访问每一个二进制位,因此,必须将用户给定的元素的范围进 行调整,调整原则是:两端适当外扩,使第一个元素的序号以及元素的个数正好成为8的倍数,这样就可以字节为单位存储集合了。即:若arrtype=set of char1..char2(事先要定义char1,char2常量),则范围扩大为newchar1..newchar2,其中newchar1=chr (ord(char1)-ord(char1) mod 8), newchar2=chr(ord(char2)+7-ord(char2) mod 8)。对于arrtype=set of '#'..'z',用户给定的范围是:#35..#122,则扩大后的实际范围是#32..#127,元素个数为96,需要用96bit=12byte表 示,故数组a中每个元素(数组中的元素)占12字节,共10个元素要占120字节。
问题:对于arrtype=set of '#'..'z'; 执行fillchar(a,sizeof(a),135)后的结果是什么呢?(135)10= (10000111)2, 数组a中每个元素如a[1]占12字节,即: 100001111000011110000111100001111000011110000111100001111000011110000111100001111000011110000111, 共96个二进制位,最低位为1,表示扩展后范围内的第1个集合元素(#32即空格)属于集合a[1],第2位为1,表示第2个元素(#33即“!”)属于 集合a[1],第3位为1,表示第3个元素(#34即“"”)属于集合a[1],第4位为0,表示第4个元素(#35即“#”)不属于集合a[1],依此 类推。其他的数组元素a[2],a[3],...,a[10]都与a[1]相同。
[例3]部分字节填充问题。前面讲的都是全部字节被填充(因为用了sizeof()函数) 对例1,若执行fillchar(a,1,55),即将变量a的第一个字节(下标最小的元素的最低字节)填充为(55)10,其原理雷同。
[小结] Fillchar(var X; Count: Word; value)过程的功能是,把指定变量X在内存段中所占的低Count个字节中的每个字节用一个字节的数据value来填充,由于各种数据类型对相同的二 进制码具有不同的解释,故最后得到的结果也大相径庭。本文探讨了各种类型数据的内部存储机制,有助于加深对数据类型的理解。
posted @ 2011-09-13 15:26 delphi初学者 阅读(33) 评论(0) 编辑
WinAPI: GetDiskFreeSpaceEx - 获取磁盘容量信息
WinAPI: GetDiskFreeSpaceEx - 获取磁盘容量信息
//声明:
GetDiskFreeSpaceEx(
lpDirectoryName: PChar; {磁盘根路径}
var lpFreeBytesAvailableToCaller: TLargeInteger; {可用空间}
var lpTotalNumberOfBytes: TLargeInteger; {总空间}
TotalFree: PLargeInteger {剩余空间}
): BOOL;
---------------------------------------------------------------------------
-----
//举例:
procedure TForm1.FormCreate(Sender: TObject);
var
d1,d2,d3: Int64;
begin
GetDiskFreeSpaceEx('C:',d1,d2,@d3);
Memo1.Clear;
with Memo1.Lines do
begin
Add(Format('可用空间: %f GB',[d1/1024/1024/1024]));
Add(Format('总空间: %f GB',[d2/1024/1024/1024]));
Add(Format('剩余空间: %f GB',[d3/1024/1024/1024]));
end;
end;
本文转自:http://www.cnblogs.com/del/archive/2008/02/11/1066914.html
posted @ 2011-09-13 09:31 delphi初学者 阅读(107) 评论(0) 编辑
GetVolumeInformation
GetVolumeInformation函数来获取硬盘的序列号
函数声明:
BOOL GetVolumeInformation(
LPCTSTR lpRootPathName, // 与获取信息卷的根路径
LPTSTR lpVolumeNameBuffer, // 用于装在卷名的一个字符串
DWORD nVolumeNameSize, // 字符串的长度
LPDWORD lpVolumeSerialNumber, // 用于装载磁盘卷序列号的变量
LPDWORD lpMaximumComponentLength, // 指定一个变量,用于装载文件名每一部分的长度
LPDWORD lpFileSystemFlags, // 用于装载一个或多个二进制位标志的长度
LPTSTR lpFileSystemNameBuffer, // 指定一个缓冲区
DWORD nFileSystemNameSize // lpFileSystemNameBuffer,的长度
);
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
Button3: TButton;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Button4: TButton;
OpenDialog1: TOpenDialog;
ComboBox1: TComboBox;
Edit5: TEdit;
Label2: TLabel;
Button5: TButton;
procedure Button4Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure ComboBox1Change(Sender: TObject);
procedure Button5Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
function gefiletime(sFilename:string;timetype:integer):tdatetime;
var
ffd:twin32finddata;
dft:dword;
lft,time:tfiletime;
h:thandle;
begin
h:=windows.FindFirstFile(pchar(sfilename),ffd);
case timetype of
0:time:=ffd.ftCreationTime;
1:time:=ffd.ftLastWriteTime;
2:time:=ffd.ftLastAccessTime;
end;
if(h<>invalid_handle_value) then
begin
windows.FindClose(h);
filetimetolocalfiletime(time,lft);
filetimetodosdatetime(lft,longrec(dft).hi,longrec(dft).lo);
result:=filedatetodatetime(dft);
end
else
result:=0;
end;
function getdiskvoiserialld(drivename:string):dword;
var
dwtemp1,dwtemp2:dword;
nresult:pdword;
begin
new(nresult);
getvolumeinformation(pchar(drivename+'\'),nil,0,nresult,dwtemp1,dwtemp2,nil,0);
result:=nresult^;
dispose(nresult);
end;
{$R *.dfm}
procedure TForm1.Button4Click(Sender: TObject);
begin
if opendialog1.Execute then
edit1.Text:=opendialog1.FileName;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
edit2.Text:=datetostr(gefiletime(edit1.text,0));
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
edit3.Text:=datetostr(gefiletime(edit1.text,1));
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
edit4.Text:=datetostr(gefiletime(edit1.text,2));
end;
procedure TForm1.ComboBox1Change(Sender: TObject);
begin
edit5.Text:=inttostr(getdiskvoiserialld(combobox1.Items[combobox1.ItemIndex]));
end;
procedure TForm1.Button5Click(Sender: TObject);
var
nu : DWORD;
Vf : DWORD;
Num : DWORD; //用来存储得到的硬盘序列号
vl : array[0..MAX_PATH] of Char; //字符串的长度
begin
GetVolumeInformation(PChar(Trim(Edit1.Text)),nil,SizeOf(vl),@Num,nu,Vf,nil,0);
Edit2.Text := IntToStr(Num);
end;
end.
posted @ 2011-09-13 09:15 delphi初学者 阅读(242) 评论(0) 编辑
FindFirstFile
VC声明
HANDLE FindFirstFile(
LPCTSTR lpFileName, // file name
LPWIN32_FIND_DATA lpFindFileData // data buffer
);
lpFileName String,欲搜索的文件名。可包含通配符,并可包含一个路径或相对路
径名
lpFindFileData WIN32_FIND_DATA,这个结构用于装载与找到的文件有关的信息。该结
构可用于后续的搜索
调用失败 返回为INVALID_HANDLE_VALUE(即-1)
typedef struct _WIN32_FIND_DATA { // wfd
DWORD dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
DWORD nFileSizeHigh;
DWORD nFileSizeLow;
DWORD dwReserved0;
DWORD dwReserved1;
TCHAR cFileName[ MAX_PATH ];
TCHAR cAlternateFileName[ 14 ];
} WIN32_FIND_DATA;
WIN32_FIND_DATA是文件查找结构体(我这样给它命名),主要作用是进行文件查找。
你可以用函数FindFirst()和FindNext()来遍历一个目录
posted @ 2011-09-12 11:06 delphi初学者 阅读(277) 评论(0) 编辑
设置文件日期信息
unit MainUnit;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TMainForm = class(TForm)
Label1: TLabel;
Edit1: TEdit;
Button1: TButton;
Label2: TLabel;
Edit2: TEdit;
Button2: TButton;
Label3: TLabel;
Edit3: TEdit;
Label4: TLabel;
Edit4: TEdit;
OpenDialog1: TOpenDialog;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.DFM}
function GetFilesTime(sFilename: String; Timetype: Integer): TDateTime;
var
ffd: TWin32FindData;
dft: DWord;
lft, Time: TFileTime;
sHandle: THandle;
begin
sHandle:= Windows.FindFirstFile(PChar(sFileName), ffd);
if (sHandle <>INVALID_HANDLE_VALUE) then
begin
case Timetype of
0: Time:= ffd.ftCreationTime;
1: Time:= ffd.ftLastWriteTime;
2: Time:= ffd.ftLastAccessTime;
end;
Windows.FindClose(sHandle);
FileTimeToLocalFileTime(Time, lft);
FileTimeToDosDateTime(lft, LongRec(dft).HI, LongRec(dft).Lo);
Result:= FileDateToDateTime(dft);
end else Result:= 0;
end;
procedure TMainForm.Button1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
Edit1.Text:= OpenDialog1.FileName;
end;
procedure TMainForm.Button2Click(Sender: TObject);
begin
if Edit1.Text<> '' then
begin
Edit2.Text:= DateToStr(GetFilesTime(Edit1.Text, 0));
Edit3.Text:= DateToStr(GetFilesTime(Edit1.Text, 1));
Edit4.Text:= DateToStr(GetFilesTime(Edit1.Text, 2));
end
else ShowMessage('请指定文件!');
end;
end.
posted @ 2011-09-12 11:05 delphi初学者 阅读(37) 评论(0) 编辑
文件函数
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
Edit2: TEdit;
Button3: TButton;
Edit3: TEdit;
Button4: TButton;
Edit4: TEdit;
Button5: TButton;
Edit5: TEdit;
Button6: TButton;
Edit6: TEdit;
Button7: TButton;
Edit7: TEdit;
Button8: TButton;
Button9: TButton;
Button10: TButton;
Edit8: TEdit;
Edit9: TEdit;
Edit10: TEdit;
OpenDialog1: TOpenDialog;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure Button6Click(Sender: TObject);
procedure Button7Click(Sender: TObject);
procedure Button8Click(Sender: TObject);
procedure Button9Click(Sender: TObject);
procedure Button10Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
if opendialog1.Execute then
begin
edit1.Text:=opendialog1.FileName;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
//将当前路径名与指定文件名合成一个绝对的文件名
edit2.Text:=expandfilename(edit1.text)
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
//获取一个以UNC格式的包括风络驱动器名的绝对文件名
edit3.Text:=expandUNCfileName(edit1.text);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
//从绝对文件名中获取目录名
edit4.Text:=ExtractFileDir(edit1.text);
end;
procedure TForm1.Button5Click(Sender: TObject);
begin
//从绝对文件名中获取驱动器名
edit5.Text:=extractfiledrive(edit1.text);
end;
procedure TForm1.Button6Click(Sender: TObject);
begin
//从绝对文件名中获取扩展名
edit6.Text:=extractfileext(edit1.text);
end;
procedure TForm1.Button7Click(Sender: TObject);
begin
//从绝对文件名中获取文件名
edit7.Text:=extractfilename(edit1.text);
end;
procedure TForm1.Button8Click(Sender: TObject);
begin
//从绝对文件名中获取路径名
edit8.Text:=extractfilepath(edit1.text);
end;
procedure TForm1.Button9Click(Sender: TObject);
begin
//从绝对文件名中获取相对于某一路径的相对路径名
edit9.Text:=extractRelativepath(edit1.text,edit4.text);
end;
procedure TForm1.Button10Click(Sender: TObject);
begin
// 将长文件名转化为短文件名
edit10.Text:=extractshortpathname(edit1.text);
end;
end.
posted @ 2011-09-12 09:18 delphi初学者 阅读(40) 评论(0) 编辑
读取文件属性 FileGetAttr
procedure TForm1.N17Click(Sender: TObject);
//读取文件属性 FileGetAttr;
var
FileName: string;
Attr: Integer; //属性值是一个整数
begin
FileName := 'F:\test\Test.txt';
Attr := FileGetAttr(FileName);
ShowMessage(IntToStr(Attr));
//属性可选值(有些用不着):
//FILE_ATTRIBUTE_READONLY = 1; 只读
//FILE_ATTRIBUTE_HIDDEN = 2; 隐藏
//FILE_ATTRIBUTE_SYSTEM = 4; 系统
//FILE_ATTRIBUTE_DIRECTORY = 16; 文件夹
//FILE_ATTRIBUTE_ARCHIVE = 32; 存档
//FILE_ATTRIBUTE_DEVICE = 64
//FILE_ATTRIBUTE_NORMAL = 128; 一般
//FILE_ATTRIBUTE_TEMPORARY = 256
//FILE_ATTRIBUTE_SPARSE_FILE = 512
//FILE_ATTRIBUTE_REPARSE_POINT = 1204
//FILE_ATTRIBUTE_COMPRESSED = 2048; 压缩
//FILE_ATTRIBUTE_OFFLINE = 4096
//FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 8192; 不被索引
//FILE_ATTRIBUTE_ENCRYPTED = 16384
end;
下面进行函数分析:
function FileGetAttr(const FileName: string): Integer;
begin
Result := GetFileAttributes(PChar(FileName));
end;
//可以看出此函数是由API函数GetFileAttributes封装而来,参数是要操作文件的文件名
//返回值是整型的属性值,如'32'表示为存档文件
posted @ 2011-09-12 05:49 delphi初学者 阅读(128) 评论(0) 编辑
WinAPI: SetCurrentDirectory、GetCurrentDirectory - 设置与获取当前目录
//声明: SetCurrentDirectory( lpPathName: PAnsiChar {路径名} ): BOOL; GetCurrentDirectory( nBufferLength: DWORD; {缓冲区大小} lpBuffer: PAnsiChar {缓冲区} ): DWORD; {返回目录实际长度} //举例: var buf: array[0..MAX_PATH] of Char; begin SetCurrentDirectory('c:\temp'); GetCurrentDirectory(SizeOf(buf), buf); ShowMessage(buf); {c:\temp} end; |
posted @ 2011-09-12 05:39 delphi初学者 阅读(85) 评论(0) 编辑
临界区对象TCriticalSection(Delphi) 与 TRtlCriticalSection 的区别
临界区对象TCriticalSection(Delphi) 与 TRtlCriticalSection 的区别
TRtlCriticalSection 是一个结构体,在windows单元中定义;
是InitializeCriticalSection,EnterCriticalSection,LeaveCriticalSection, DeleteCriticalSection 等这几个kernel32.dll中的临界区操作API的参数;
TCriticalSection是在SyncObjs单元中实现的类,它对上面的那些临界区操作API函数进行了了封装,简化并方便了在Delphi的使用;
如TCriticalSection.Enter;就是调用了EnterCriticalSection这个API函数。
多线程程序中,如果各个线程要访问同一个资源,如同一个变量
这时就要使用线程同步技术,才不会使线程之间产生冲突和干扰
线程同步有多种办法,使用临界区是其中最简单,也是效率最高的办法(CPU占用时间最少)
使用临界区代码如下:
先声明一个TRTLCriticalSection类型的全局变量
var
MyCs:TRTLCriticalSection;
在程序开始或建立线程之前,初始化
InitializeCriticalSection(MyCs);//初始化临界区
在程序结束或所有线程结束后,删除它
DeleteCriticalSection(MyCs);//删除临界区
再在线程中要同步的地方加入
EnterCriticalSection(MyCs); //进入临界区
try
//程序代码
finally
LeaveCriticalSection(MyCs); //离开临界区
end;