2进制文件的读写 [会者拿分](100分)

  • 主题发起人 主题发起人 陈礼泉
  • 开始时间 开始时间

陈礼泉

Unregistered / Unconfirmed
GUEST, unregistred user!
我想建一个自己的数据文件
要求如下:
文件头为:
TFileHead = record
FileType : string[4] ;
//比如自定为: RIMF
CopyRight : string[20] ;
//版权说明
Aowner : string[16] ;
//作者
CreateDate : TDate ;
//创建日期
end;
数据部分:
TFileData = record
Name : string[8] ;
Age : integer ;
Sex : string[2];
end;

读写文件,我的想发是这样的:
procedure read;
var
readfile : file ;
begin
AssignFile(readfile,FileName);
reset(readfile);
BlockRead(...);
....
CloseFile(readfile);
end;

procedure write;
var
writefile : file ;
begin
AssignFile(writefile,FileName);
rewrite(writefile);
BlockWrite(...);
....
CloseFile(wrtiefile);
end;

现在我使用的BlockRead和BlockWrite,读出来的数据总是不正确,所以
请个位写一个简单的源程序(有读写功能)给我[在文件中储存多条数据,只有一
个文件头,多个数据块],100分奉上.(您也可以采用更好的方法都文件)
 
不用string,改用array [0..N] of Char.另外最好用Packed record
 
其实你写玩一个DATA后,加入一个结束的标志就可以了,比如说遇见(****)时表示
一个记录已经结束!读的时候判断一下,不过这种方法很笨,只是提供一个想法!
 
我要具体的代码(那怕是最简单的)
 

TFileHead = record
FileType : char[4] ;
//比如自定为: RIMF
CopyRight : char[20] ;
//版权说明
Aowner : char[16] ;
//作者
CreateDate : TDate ;
//创建日期
end;
数据部分:
TFileData = record
Name : char[8] ;
Age : integer ;
Sex : char[2];
end;

procedure read;
var
readfile : file ;
begin
AssignFile(readfile,FileName);
reset(readfile);
BlockRead(...);
....
CloseFile(readfile);
end;

procedure write;
var
writefile : file ;
begin
AssignFile(writefile,FileName);
rewrite(writefile);
BlockWrite(...);
....
CloseFile(wrtiefile);
end;

 
给你个我前段时间写的一个程序中的片段:
TFileHeadRec = record
Fzqdm: string[6];
Fpos: integer;
Flen: integer;
end;
TMinRec = record
Fdate: string[8];
Ftime: string[4];
Fprice: integer;
Fvol: integer;
Fsorb: string[1];
end;
procedure TForm1.InitMinFile;
var
fpos, i, j, kk: integer;
tmpMinRec: array[0..2419] of TMinRec;
fp: TFileStream;
c: string;
begin
try
for i := 0 to 2419 do
begin
tmpMinRec.Fdate := '19000101';
tmpMinRec.Ftime := '1200';
tmpMinRec.Fprice := 0;
tmpMinRec.Fvol := 0;
tmpMinRec.Fsorb := '0';
end;
FileHeadArrTotal := Allzqdm.count;
for i := 0 to Allzqdm.Count - 1 do
begin
FileHeadArr.Fzqdm := Allzqdm;
FileHeadArr.Flen := 242 * 10 * sizeof(TMinRec);
try
fpos := strtoint(FFilePos);
FileHeadArr.Fpos := FILEDATAPOS + fpos * 242 * 10 * sizeof(TMinRec);
except
end;
end;
if (not fileexists(pathmin + 'min.dat')) then
begin
try
fp := TFileStream.Create(pathmin + 'min.dat', fmCreate or fmShareDenyNone);
fp.Seek(0, soFrombegin
ning);
fp.Write(FileHeadArrTotal, 4);
fp.WriteBuffer(FileHeadArr, sizeof(TFileHeadRec) * High(FileHeadArr));
i := 0;
for kk := 0 to FileHeadArrTotal - 1 do
begin
fp.Seek(FileHeadArr[kk].Fpos, soFrombegin
ning);
fp.Write(i, 4);
fp.WriteBuffer(tmpMinRec, sizeof(TMinRec) * 2420);
end;
finally
fp.free;
end;
end
else
begin
try
fp := TFileStream.Create(pathmin + 'min.dat', fmOpenWrite or fmShareDenyNone);
fp.Seek(0, soFrombegin
ning);
fp.Write(FileHeadArrTotal, 4);
fp.WriteBuffer(FileHeadArr, sizeof(TFileHeadRec) * High(FileHeadArr));
i := 0;
for kk := 0 to FileHeadArrTotal - 1 do
begin
fp.Seek(FileHeadArr[kk].Fpos, soFrombegin
ning);
fp.Write(i, 4);
//fp.WriteBuffer(tmpMinRec, sizeof(TMinRec) * 2420);
end;
finally
fp.Free;
end;
end;
if (not FileExists(path242 + '242.dat')) then
begin
try
fp := TFileStream.Create(path242 + '242.dat', fmCreate or fmShareDenyNone);
fp.Seek(0, soFrombegin
ning);
fp.Write(FileHeadArrTotal, 4);
fp.WriteBuffer(FileHeadArr, sizeof(TFileHeadRec) * High(FileHeadArr));
i := 0;
for kk := 0 to FileHeadArrTotal - 1 do
begin
fp.Seek(FileHeadArr[kk].Fpos, soFrombegin
ning);
fp.Write(i, 4);
fp.WriteBuffer(tmpMinRec, sizeof(TMinRec) * 2420);
end;
finally
fp.free;
end;
end
else
begin
try
fp := TFileStream.Create(path242 + '242.dat', fmOpenWrite or fmShareDenyNone);
fp.Seek(0, soFrombegin
ning);
fp.Write(FileHeadArrTotal, 4);
fp.WriteBuffer(FileHeadArr, sizeof(TFileHeadRec) * High(FileHeadArr));
i := 0;
for kk := 0 to FileHeadArrTotal - 1 do
begin
fp.Seek(FileHeadArr[kk].Fpos, soFrombegin
ning);
fp.Write(i, 4);
//fp.WriteBuffer(tmpMinRec, sizeof(TMinRec) * 2420);
end;
finally
fp.free;
end;
end;
except
end;
end;

procedure TForm1.NewWrite242(ptr: pTsshqRec);
var
i, cpos, rectotal: integer;
tmpRec: TMinRec;
c: string;
begin
try
rectotal := 0;
cpos := Allzqdm.IndexOf(ptr.zqdm);
if (cpos >= 0) then
begin
try
tmpRec.Fdate := ptr.F242_hqrq;
tmpRec.Ftime := ptr.F242_time;
tmpRec.Fprice := round(ptr.F242_price * 1000);
tmpRec.Fvol := round(ptr.F242_vol * 100);
if (ptr.F242_time = '0930') then
tmpRec.Fvol := round((ptr.zs - ptr.xs) * 100);
if (ptr.sorb) then
tmpRec.Fsorb := '1' //sale
else
tmpRec.Fsorb := '0';
//buy
fp242.Seek(FileHeadArr[cpos].Fpos, soFrombegin
ning);
fp242.Read(rectotal, sizeof(rectotal));
fp242.Seek(rectotal * sizeof(TMinRec), soFromCurrent);
fp242.Write(tmpRec, sizeof(TMinRec));
inc(rectotal);
fp242.Seek(FileHeadArr[cpos].Fpos, soFrombegin
ning);
fp242.Write(rectotal, 4);
except
end;
end;
except
end;
end;
procedure TForm1.Newread242(zqdm: string);
var
fp: tfilestream;
FileHeadArr: array[0..2000] of TFileHeadRec;
FileHeadArrTotal: integer;
MinArr: array[0..2419] of TMinRec;
MinTotal: integer;
i, cpos: integer;
begin
MapArrTotal := -1;
cpos := AllZqdm.IndexOf(zqdm);
if (cpos >= 0) then
begin
try
fp := TfileStream.Create(path242 + '242.dat', fmOpenRead or fmShareDenyNone);
try
fp.Seek(0, soFrombegin
ning);
fp.Read(FileHeadArrTotal, 4);
fp.ReadBuffer(FileHeadArr, sizeof(TFileHeadRec) * FileHeadArrTotal);
fp.Seek(FileHeadArr[cpos].Fpos, soFrombegin
ning);
fp.Read(MinTotal, 4);
fp.ReadBuffer(MinArr, sizeof(TMinRec) * MinTotal);
for i := 0 to MinTotal - 1 do
begin
MapArr.time := MinArr.Ftime;
MapArr.price := MinArr.Fprice / 1000;
MapArr.vol := MinArr.Fvol / 100;
end;
MapArrTotal := MinTotal;
finally
fp.Free;
end;
except
end;
end;
end;

 
我给你讲一个,比如每个字段用#1b记录与记录用#1b#0d隔开,
这样就可以了!
 
我只提醒你一下:Reset函数可以有第二个参数,是记录快的大小!
Reset(F,SizeOf(FileHead));
BlockRead(F,Buf,1,...);这个时候,读取的是FileHead整个记录块!
如果有不同记录保存到文件里面,那么直接使用Reset(F)即可。
BlockRead(F,Buf,1,SizeOf(Buf));
 
listening...
 
请看:
记录类型文件读取错误的讨论,也许对您有用:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=792509
如果您要使用string成员的话,您必须手工保存string的值和长度.
在结构中系统保存的是string的地址(4个字节).
 
{近来忙,答应了一个MM给她写一个程序,现在有点后悔。
这个程序可以实现你所要的结果,但并不令人满意,实际上要用到TLIST保存FileData(我一向都是这样做的),
可以在此基础上作点更改}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TFileHead = record
FileType : string[4] ;
//比如自定为: RIMF
CopyRight : string[20] ;
//版权说明
Aowner : string[16] ;
//作者
CreateDate : TDate ;
//创建日期
end;
//数据部分
TFileData = record
Name : string[8] ;
Age : integer ;
Sex : string[2];
end;

type
TForm1 = class(TForm)
BtnInitialize: TButton;
BtnRead: TButton;
BtnWrite: TButton;
Memo1: TMemo;
procedure BtnInitializeClick(Sender: TObject);
procedure BtnReadClick(Sender: TObject);
procedure BtnWriteClick(Sender: TObject);
private
Head : TFileHead;
Data : TFileData;
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.BtnInitializeClick(Sender: TObject);//定义文件内容
begin
//定义头
Head.FileType := 'RIMF';
//比如自定为: RIMF
Head.CopyRight := 'v1.0' ;
//版权说明
Head.Aowner := 'shadow' ;
//作者
Head.CreateDate := now;
//创建日期
//定义内容,仅仅示例,实际上要用指针及TLIST操作。
Data.Name := '12';
Data.Age := 23 ;
DAta.Sex := '1';
BtnRead.Enabled := true;
BtnWrite.Enabled := true;
end;

procedure TForm1.BtnReadClick(Sender: TObject);
var
readfile : file of byte;
ReadHead : TFileHead;
ReadData : TFileData;
CountRead : integer;
begin
AssignFile(readfile,'c:/test.rf');
//可用OpenDialog
reset(readfile);
BlockRead(readfile,ReadHead,sizeof(TFileHead),CountRead);
if CountRead <> sizeOf(TFileHead) then
begin
showmessage('error');
exit;
end;
memo1.Lines.Add('AOwner: '+ReadHead.Aowner);//读出看看是否已经在内容
repeat
BlockRead(ReadFile,ReadData,sizeof(TFileData));//可以加上检测
memo1.Lines.Add('Name: '+ReadData.Name);
until eof(ReadFile);
CloseFile(readfile);
end;

procedure TForm1.BtnWriteClick(Sender: TObject);
var
writefile : file of byte;
i : integer;
begin
AssignFile(writefile,'c:/test.rf');
//可以SaveDialog
rewrite(writefile);
BlockWrite(WriteFile,Head,sizeof(TFileHead));
for i := 1 to (sizeof(Data) div sizeof(TFileData)) do
begin
BlockWrite(WriteFile,Data,sizeof(TFileData));
//可以加上检测
end;
CloseFile(WriteFile);
end;

end.
 
谢谢大家的参与
 

Similar threads

后退
顶部