前言:
Delphi 支持三种文件类型: 文本文件、记录文件、无类型文件。
文本文件是以行为单位进行读、写的。由于每一行的长度不一定相同,不能计算出给定行在文件中的确切位置,因而只能顺序地读写。
文本文件只能单独为读或写而打开,在一个打开的文本文件上同时进行读、写操作是不允许的。
文本文件的打开需要两个步骤:1.文件变量与文件名关联;2.初始化读写。
1.文件变量与文件名关联:
AssignFile(VarTxt, FileName);
FileName 如果省略路径将默认当前目录。
2.初始化读写有三种方式:
(1) Reset: 只读打开, 指针移到文件头;
(2) Rewrite: 创建新文件并打开, 只写;
(3) Append: 从尾部追加, 指针当然在文件尾。
文件不存在时使用 Reset 或 Append 会引发一个I/O异常。
最后用 CloseFile 关闭文件。
为保持兼容,Delphi 也允许用户用 Assign 建立关联, 用 Close 关闭文件。
//读写示例: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; Button6: TButton; Button7: TButton; 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); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} var F: Text; //TextFile 和 Text 是一样的 FileName: string = 'c:/temp/test.txt'; //写文件 procedure TForm1.Button1Click(Sender: TObject); begin AssignFile(F,FileName); Rewrite(F); //会覆盖已存在的文件 Writeln(F, '第一行'); Writeln(F, '第二行'); CloseFile(F); end; //读文件(先执行写文件) procedure TForm1.Button2Click(Sender: TObject); var s: string; begin AssignFile(F,FileName); Reset(F); //只读打开 Readln(F, s); //读取 ShowMessage(s); //显示: 第一行 Readln(F, s); //继续读取 ShowMessage(s); //显示: 第二行 CloseFile(F); end; //追加 procedure TForm1.Button3Click(Sender: TObject); begin AssignFile(F,FileName); Append(F); //打开准备追加 Writeln(F, '第三行'); Writeln(F, '第四行'); CloseFile(F); end; //读取全部(需要Memo帮忙显示) procedure TForm1.Button4Click(Sender: TObject); var s: string; begin AssignFile(F,FileName); Reset(F); //只读打开 Memo1.Clear; while not Eof(F) do begin Readln(F, s); Memo1.Lines.Add(s); end; CloseFile(F); end; //分列写入 procedure TForm1.Button5Click(Sender: TObject); //这个过程级函数的功能是: 用空格把 s 凑够 n 的长度 function AddSpace(s: string; n: Word): string; begin while Length(s) < n do begin s := s + ' '; end; Result := s; end; var name: string[8]; address: string[16]; begin AssignFile(F, FileName); Rewrite(F); name := '张三'; name := AddSpace(name,8); address := '山东泰安'; address := AddSpace(address,16); Writeln(F, name, address); name := '李四儿'; name := AddSpace(name,8); address := '贵州省安顺黄果树'; address := AddSpace(address,16); Writeln(F, name, address); name := '王二麻子'; name := AddSpace(name,8); address := '北京市海淀区'; address := AddSpace(address,16); Writeln(F, name, address); CloseFile(F); {写入的结果是: 张三 山东泰安 李四儿 贵州省安顺黄果树 王二麻子北京市海淀区 } end; //分列读取 procedure TForm1.Button6Click(Sender: TObject); var name: string[8]; address: string[16]; begin AssignFile(F, FileName); Reset(F); Memo1.Clear; while not Eof(F) do begin Readln(F, name); Memo1.Lines.Add(name); end; CloseFile(F); Reset(F); while not Eof(F) do begin Readln(F, name, address); Memo1.Lines.Add(address); end; CloseFile(F); {读取结果: 张三 李四儿 王二麻子 山东泰安 贵州省安顺黄果树 北京市海淀区 } end; //不同数据类型的写入和读取 procedure TForm1.Button7Click(Sender: TObject); var name: string[6]; age: Word; birthday: TDate; begin AssignFile(F,FileName); Rewrite(F); name := '菜花 '; //加两个空格凑够6个字符 age := 18; birthday := StrToDate(DateToStr(Now-18*365)); //假如她今天过生日 Writeln(F,name,age,birthday); CloseFile(F); Reset(F); Readln(F,name,age,birthday); Memo1.Clear; Memo1.Lines.Add(name); Memo1.Lines.Add(IntToStr(age)); Memo1.Lines.Add(DateToStr(birthday)); CloseFile(F); {读取结果: 菜花 18 1989-12-23 } //其实这样的东西应该用类型文件操作更合适, 但如果有这样的文本文件让你读取呢? end; end.
纲要:
AssignFile: 关联
Rewrite: 创建并打开一个新文件, 如已存在则覆盖
Reset: 打开已存在的文件; 追加也要用它先打开, 然后再移动指针; Append 是文本文件专用的
CloseFile: 关闭
FileSize: 记录数
FilePos: 返回文件的当前位置
Seek: 把文件指针移到指定位置(只用于结构化文件)
Eof: 文件尾
Read: 读
Write: 写
另外: 包含长字符串、变量、类实例、接口或动态数组的记录不能写入类型文件中!
//操作示例: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} type TPersonRec = packed record name: string[12]; age: Word; birthday: TDate; end; //先定义一个结构 var DataFile: file of TPersonRec; //声明 DataFile 用来读写 TPersonRec 结构数据 PersonRec: TPersonRec; //声明结构变量 FileName: string = 'c:/temp/test.dat'; //准备操作的文件 //创建并写入文件 procedure TForm1.Button1Click(Sender: TObject); begin AssignFile(DataFile,FileName); //关联文件 Rewrite(DataFile); //建立文件, 如果存在就覆盖 PersonRec.name := '张三'; PersonRec.age := 18; PersonRec.birthday := StrToDate('1990-1-1'); Write(DataFile,PersonRec); //写入 PersonRec.name := '李四儿'; PersonRec.age := 81; PersonRec.birthday := StrToDate('1927-11-11'); Write(DataFile,PersonRec); //写入 CloseFile(DataFile); //关闭 end; //追加数据 procedure TForm1.Button2Click(Sender: TObject); begin AssignFile(DataFile,FileName); Reset(DataFile); //Append 只对文本文件 Seek(DataFile,FileSize(DataFile)); //移到文件尾, 这里的 FileSize 表示有多少条记录 PersonRec.name := '王二麻子'; PersonRec.age := 1; PersonRec.birthday := StrToDate('2006-12-19'); Write(DataFile,PersonRec); PersonRec.name := '嫦娥'; PersonRec.age := 2000; PersonRec.birthday := StrToDate('0007-7-7'); Write(DataFile,PersonRec); CloseFile(DataFile); end; //读取数据(用Memo显示数据吧) procedure TForm1.Button3Click(Sender: TObject); begin AssignFile(DataFile,FileName); Reset(DataFile); Memo1.Clear; Read(DataFile,PersonRec); //读取一条, 指针自动移到下一条 Memo1.Lines.Add(PersonRec.name); Memo1.Lines.Add(IntToStr(PersonRec.age)); Memo1.Lines.Add(DateToStr(PersonRec.birthday)); Read(DataFile,PersonRec); //读取下一条 Memo1.Lines.Add(PersonRec.name); Memo1.Lines.Add(IntToStr(PersonRec.age)); Memo1.Lines.Add(DateToStr(PersonRec.birthday)); Seek(DataFile,FileSize(DataFile)-1); //指针移到最好一条 Read(DataFile,PersonRec); Memo1.Lines.Add(PersonRec.name); Memo1.Lines.Add(IntToStr(PersonRec.age)); Memo1.Lines.Add(DateToStr(PersonRec.birthday)); CloseFile(DataFile); {显示结果: 张三 18 1990-1-1 李四儿 81 1927-11-11 嫦娥 2000 0007-7-7 } end; //修改数据 procedure TForm1.Button4Click(Sender: TObject); begin AssignFile(DataFile,FileName); Reset(DataFile); Seek(DataFile,3); //指针移到第四条 Read(DataFile,PersonRec); //读取 PersonRec.age := 0; PersonRec.birthday := StrToDate('2007-10-24'); Seek(DataFile,3); //指针移到第四条 Write(DataFile,PersonRec); //写入 CloseFile(DataFile); end; //读取所有数据 procedure TForm1.Button5Click(Sender: TObject); begin AssignFile(DataFile,FileName); Reset(DataFile); Memo1.Clear; while not Eof(DataFile) do begin Memo1.Lines.Add('第 ' + IntToStr(FilePos(DataFile)+1) + ' 条:'); Read(DataFile,PersonRec); Memo1.Lines.Add(PersonRec.name); Memo1.Lines.Add(IntToStr(PersonRec.age)); Memo1.Lines.Add(DateToStr(PersonRec.birthday)); Memo1.Lines.Add(''); //来个空行 end; CloseFile(DataFile); {显示结果: 第 1 条: 张三 18 1990-1-1 第 2 条: 李四儿 81 1927-11-11 第 3 条: 王二麻子 1 2006-12-19 第 4 条: 嫦娥 0 2007-10-24 } end; end.
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; Button6: TButton; Button7: TButton; 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); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} const FileName = 'c:/temp/binary.dat'; var F: file; //用无类型的方式写入一个字节 procedure TForm1.Button1Click(Sender: TObject); var b: Byte; begin AssignFile(F,FileName); Rewrite(F,1); //第二个参数表示: 把 1 个字节当作一个写入单位 b := 65; BlockWrite(F,b,1); //写入; 参数2是要写入的内容; 参数3表示写入 1 次. CloseFile(F); //落实 binary.dat 的大小: 1个字节; 内容: A (可用记事本打开) end; //用无类型的方式读出一个字节 procedure TForm1.Button2Click(Sender: TObject); var b: Byte; begin AssignFile(F,FileName); Reset(F,1); //把 1 个字节当作一个读取单位 BlockRead(F,b,1); //读取一次; 放入 b ShowMessage(Chr(b)); //A CloseFile(F); end; //写入更多字节 procedure TForm1.Button3Click(Sender: TObject); var buffer: array[0..127] of Byte; i: Integer; //储存多个字节, 需要用数组了 begin for i := Low(buffer) to High(buffer) do buffer[i] := i; //给数组赋值, 注意现在数组大小是 128 AssignFile(F,FileName); Rewrite(F,32); //规定把 32 个字节当作一个读取单位, 注意这个数字和缓冲区大小必须是倍数关系 BlockWrite(F,buffer,4); //需要写入几次呢? 128/32=4 CloseFile(F); //写成的文件肯定是128字节大小, 但用记事本可能看不了, 因为这个二进制不是文本 end; //读出 procedure TForm1.Button4Click(Sender: TObject); var buffer: array[0..127] of Byte; i: Integer; begin AssignFile(F,FileName); Reset(F,4); //把 4 字节当作一个读取单位; 为了那个倍数关系, 这里一般是 1 BlockRead(F,buffer,32); //当然需要 32 次才能读完 CloseFile(F); //怎么显示一下呢? 还是用 Memo 吧; 显示字符? 数字? 还是十六进制吧 Memo1.Clear; for i := Low(buffer) to High(buffer) do begin Memo1.Lines.Add(IntToHex(buffer[i],1)); end; (*显示结果: 0 1 2 3 ... 7D 7E 7F *) end; //读写 Char 与实际读写字节 procedure TForm1.Button5Click(Sender: TObject); var cArr1,cArr2: array[0..4] of Char; i: Integer; num: Integer; //记录实际读写的字节数 begin for i := Low(cArr1) to High(cArr1) do cArr1[i] := Chr(65+i); //填充 A B C D E AssignFile(F,FileName); Rewrite(F,1); //建立 BlockWrite(F,cArr1,Length(cArr1),num); //参数4: num 是实际写入的字节数 ShowMessage(IntToStr(num)); //5 Reset(F,1); //重新打开 BlockRead(F,cArr2,Length(cArr2),num); //参数5: num 是实际读出的字节数 ShowMessage(IntToStr(num)); //5 ShowMessage(cArr2); //ABCDE CloseFile(F); end; //写入长字符串, 读出其十六进制码 procedure TForm1.Button6Click(Sender: TObject); var p: PChar; b: Byte; begin p := '万一的 Delphi 博客'; AssignFile(F,FileName); //关联文件名 Rewrite(F,1); //创建并打开 BlockWrite(F,p,Length(p)); //写入 FileMode := fmOpenRead; //这时可以设文件为只读 Reset(F,1); //为读取打开 Memo1.Clear; while not Eof(F) do begin BlockRead(F,b,1); Memo1.Text := Memo1.Text + IntToHex(b,2) + ' '; end; //显示结果: 70 F0 45 00 08 F7 12 00 A6 FB 43 00 A0 1A E5 00 FF C5 CloseFile(F); end; //复制个文件 procedure TForm1.Button7Click(Sender: TObject); var FromF,ToF: file; NumRead,NumWritten: Integer; Buffer: array[1..2048] of Byte; begin AssignFile(FromF, 'c:/temp/test1.dat'); //假定有这个文件 Reset(FromF, 1); AssignFile(ToF, 'c:/temp/test2.dat'); Rewrite(ToF, 1); repeat BlockRead(FromF, Buffer, SizeOf(Buffer), NumRead); BlockWrite(ToF, Buffer, NumRead, NumWritten); until (NumRead = 0) or (NumWritten <> NumRead); { NumRead=0 表示读完了; NumWritten <> NumRead 表示磁盘空间不够了 } CloseFile(FromF); CloseFile(ToF); end; end.
时间: 2024-09-28 18:01:05