文本文件读写
前言: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.