Pascal 中的 FileIO 问题
Trouble with FileIO in Pascal
我在为我的编程入门 class 中的最终项目创建工作保存系统时遇到了问题。我正在尝试将狗的记录保存在数组中。每只狗都有名字、主人姓名、品种、性别(1 和 2 与是和否相关)、绝育/绝育状态(同样 1 和 2 与是和否相关),以及一系列体重和 BCS 分数存储在记录中,所有这些都绘制在整个狗数组的单独索引中。我设置的系统完美地导入了一只狗,但是一旦我添加另一只狗被带到终端,我就会收到有关访问冲突的错误。我已经手动执行了很多次,但似乎找不到问题所在。我将在下面附上代码。谢谢!!!
type
DogInformation = record
OwnerName: String;
name: String;
breed: String;
gender: Integer;
weight: array of Integer;
spay_neut: Integer;
bcs: array of Integer;
end;
DogArray = array of DogInformation;
procedure SaveAllData(var dog: DogArray);
var
i, o, z: Integer;
StoredData: Text;
len: Integer;
begin
FileCreate('/Users/Nat/Desktop/data.txt');
AssignFile(StoredData, '/Users/Nat/Desktop/data.txt');
Reset(StoredData);
Rewrite(StoredData);
for i := 0 to (High(dog) - 1) do
begin
WriteLn(StoredData, '!');
WriteLn(StoredData, dog[i].name);
WriteLn(StoredData, '@');
WriteLn(StoredData, dog[i].OwnerName);
WriteLn(StoredData, '#');
WriteLn(StoredData, dog[i].breed);
WriteLn(StoredData, '$');
WriteLn(StoredData, dog[i].gender);
WriteLn(StoredData, '%');
WriteLn(StoredData, dog[i].spay_neut);
for o := 0 to High(dog[i].weight) do
begin
WriteLn(StoredData, '^');
WriteLn(StoredData, dog[i].weight[o]);
end;
for z := 0 to High(dog[i].bcs) do
begin
WriteLn(StoredData, '&');
WriteLn(StoredData, dog[i].bcs[z]);
end;
WriteLn(StoredData, '?');
end;
len := (Length(dog) - 1);
WriteLn(StoredData, '!');
WriteLn(StoredData, dog[len].name);
WriteLn(StoredData, '@');
WriteLn(StoredData, dog[len].OwnerName);
WriteLn(StoredData, '#');
WriteLn(StoredData, dog[len].breed);
WriteLn(StoredData, '$');
WriteLn(StoredData, dog[len].gender);
WriteLn(StoredData, '%');
WriteLn(StoredData, dog[len].spay_neut);
for o := 0 to High(dog[len].weight) do
begin
WriteLn(StoredData, '^');
WriteLn(StoredData, dog[len].weight[o]);
end;
for z := 0 to High(dog[len].bcs) do
begin
WriteLn(StoredData, '&');
WriteLn(StoredData, dog[len].bcs[z]);
end;
WriteLn(StoredData, '~');
Close(StoredData);
end;
procedure LoadAllData(var dog: DogArray);
var
ident: String;
i, o, z: Integer;
StoredData: Text;
skip: String;
begin
AssignFile(StoredData, '/Users/Nat/Desktop/data.txt');
Reset(StoredData);
i := 0;
o := 0;
z := 0;
SetLength(dog,1);
SetLength(dog[i].weight,0);
SetLength(dog[i].bcs,0);
repeat
begin
ReadLn(StoredData, ident);
if ident = '!' then
begin
WriteLn('Importing Dogs Name.......');
ReadLn(StoredData, dog[i].name);
WriteLn(dog[i].name);
end;
if ident = '?' then
begin
SetLength(dog, (Length(dog))+1);
i := i + 1;
end;
if ident = '@' then
begin
WriteLn('Importing Owner Name......');
ReadLn(StoredData, dog[i].OwnerName);
WriteLn(dog[i].OwnerName);
end;
if ident = '#' then
begin
WriteLn('Importing Breed...........');
ReadLn(StoredData, dog[i].breed);
WriteLn(dog[i].breed);
end;
if ident = '$' then
begin
WriteLn('Importing Gender..........');
ReadLn(StoredData, dog[i].gender);
WriteLn(dog[i].gender);
end;
if ident = '%' then
begin
WriteLn('Importing Spay/Neut.......');
ReadLn(StoredData, dog[i].spay_neut);
WriteLn(dog[i].spay_neut);
end;
if ident = '^' then
begin
WriteLn('Importing Weights.........');
SetLength(dog[i].weight, (Length(dog[i].weight))+1);
ReadLn(StoredData, (dog[i].weight[o]));
WriteLn(dog[i].weight[o], ' ');
o := o + 1;
end;
if ident = '&' then
begin
WriteLn('Importing BCS.............');
SetLength(dog[i].bcs, (Length(dog[i].bcs))+1);
ReadLn(StoredData, (dog[i].bcs[z]));
WriteLn(dog[i].bcs[z], ' ');
z := z + 1;
end;
end;
until ident = '~';
WriteLn('');
WriteLn('Import Complete...........');
Close(StoredData);
end;
任何信息或建议都会有所帮助!
谢谢,纳特
编辑 - 这是第二只狗在终端中的输出。除了 dogs Weight 和 BCS 之外的所有内容都出来了,然后当我尝试通过添加新狗来编辑 dog 数组时,程序以访问冲突为由退出。
您需要在循环的每次迭代中仔细重新初始化加载过程中的变量:
i := 0;
repeat
o := 0;
z := 0;
SetLength(dog, i+1);
SetLength(dog[i].weight, 0);
SetLength(dog[i].bcs, 0);
...
inc(i);
until...
否则 o
和 z
变量递增到高于 weight 和 bcz 数组上边界的值。
我决定也写一个答案。我已经给出了一个答案,说明了您问题的确切解决方案。但是我觉得我需要解释一下,您使用的方法从一开始就不是最佳的……这不是使用 Pascal 方言的方式。
让我们开始吧。
首先。 Pascal 开发人员通常在用户定义类型的名称前使用 T
:我重命名了记录声明。这是声明。
type
TDogInformation = record
OwnerName: String;
// other fields...
end;
下一步。我声明了以下变量:
var
fl: file;
RecSize: word; // This variable will be used for fast data access
DI: array of TDogInformation;
i: word;
我以这种方式填充数据,您可以使用任何其他方式。
Setlength(DI, 2);
with DI[0] do
begin
OwnerName := 'First owner';
name := 'First dog';
breed := 'Mixed';
gender := 0;
Setlength(weight, 2);
weight[0] := 56;
weight[1] := 60;
spay_neut := 1;
Setlength(bcs, 1);
bcs[0] := 15;
end;
with DI[1] do
begin
OwnerName := 'Second owner';
name := 'Second dog';
breed := 'Mixed mixed';
gender := 1;
Setlength(weight, 1);
weight[0] := 64;
spay_neut := 1;
Setlength(bcs, 12);
bcs[0] := 16;
bcs[1] := 18;
end;
现在我们进行数据的快速写入。整个过程只需要几行代码。
AssignFile(fl, 'b:\asd.txt');
ReWrite(fl);
for i := 0 to High(DI) do
begin
RecSize := SizeOf(DI[i]); //<--We calculate and keep the buffer size
BlockWrite(fl, RecSize, 2); //<--and write it in the file to simlify reading
BlockWrite(fl, DI[i], RecSize);//<--Now we write the record at once.
end;
CloseFile(fl);
下面是快速阅读。
AssignFile(fl, 'b:\asd.txt');
SetLength(DI, 0);//line is compulsory. We reinitialize DI
Reset(fl);
i := 0;
repeat
Setlength(DI, i+1);
BlockRead(fl, RecSize, SizeOf(RecSize) { =2 as it is a word });
//^ You will get the record size by reading the word variable first
BlockRead(fl, DI[i], RecSize); //Now read the record using its fetched size
WriteLn(DI[i].OwnerName);//output the records' data
Inc(i);
until Eof(fl);
CloseFile(fl);
ReadLn;
就是这样。您确实需要解析文本数据。最后。有一些技术允许一次写入整个集合(例如,使用 TStream/TMemoryStream/TFileStream)而无需任何解析 and/or setting/fetching 单个记录的长度。
我在为我的编程入门 class 中的最终项目创建工作保存系统时遇到了问题。我正在尝试将狗的记录保存在数组中。每只狗都有名字、主人姓名、品种、性别(1 和 2 与是和否相关)、绝育/绝育状态(同样 1 和 2 与是和否相关),以及一系列体重和 BCS 分数存储在记录中,所有这些都绘制在整个狗数组的单独索引中。我设置的系统完美地导入了一只狗,但是一旦我添加另一只狗被带到终端,我就会收到有关访问冲突的错误。我已经手动执行了很多次,但似乎找不到问题所在。我将在下面附上代码。谢谢!!!
type
DogInformation = record
OwnerName: String;
name: String;
breed: String;
gender: Integer;
weight: array of Integer;
spay_neut: Integer;
bcs: array of Integer;
end;
DogArray = array of DogInformation;
procedure SaveAllData(var dog: DogArray);
var
i, o, z: Integer;
StoredData: Text;
len: Integer;
begin
FileCreate('/Users/Nat/Desktop/data.txt');
AssignFile(StoredData, '/Users/Nat/Desktop/data.txt');
Reset(StoredData);
Rewrite(StoredData);
for i := 0 to (High(dog) - 1) do
begin
WriteLn(StoredData, '!');
WriteLn(StoredData, dog[i].name);
WriteLn(StoredData, '@');
WriteLn(StoredData, dog[i].OwnerName);
WriteLn(StoredData, '#');
WriteLn(StoredData, dog[i].breed);
WriteLn(StoredData, '$');
WriteLn(StoredData, dog[i].gender);
WriteLn(StoredData, '%');
WriteLn(StoredData, dog[i].spay_neut);
for o := 0 to High(dog[i].weight) do
begin
WriteLn(StoredData, '^');
WriteLn(StoredData, dog[i].weight[o]);
end;
for z := 0 to High(dog[i].bcs) do
begin
WriteLn(StoredData, '&');
WriteLn(StoredData, dog[i].bcs[z]);
end;
WriteLn(StoredData, '?');
end;
len := (Length(dog) - 1);
WriteLn(StoredData, '!');
WriteLn(StoredData, dog[len].name);
WriteLn(StoredData, '@');
WriteLn(StoredData, dog[len].OwnerName);
WriteLn(StoredData, '#');
WriteLn(StoredData, dog[len].breed);
WriteLn(StoredData, '$');
WriteLn(StoredData, dog[len].gender);
WriteLn(StoredData, '%');
WriteLn(StoredData, dog[len].spay_neut);
for o := 0 to High(dog[len].weight) do
begin
WriteLn(StoredData, '^');
WriteLn(StoredData, dog[len].weight[o]);
end;
for z := 0 to High(dog[len].bcs) do
begin
WriteLn(StoredData, '&');
WriteLn(StoredData, dog[len].bcs[z]);
end;
WriteLn(StoredData, '~');
Close(StoredData);
end;
procedure LoadAllData(var dog: DogArray);
var
ident: String;
i, o, z: Integer;
StoredData: Text;
skip: String;
begin
AssignFile(StoredData, '/Users/Nat/Desktop/data.txt');
Reset(StoredData);
i := 0;
o := 0;
z := 0;
SetLength(dog,1);
SetLength(dog[i].weight,0);
SetLength(dog[i].bcs,0);
repeat
begin
ReadLn(StoredData, ident);
if ident = '!' then
begin
WriteLn('Importing Dogs Name.......');
ReadLn(StoredData, dog[i].name);
WriteLn(dog[i].name);
end;
if ident = '?' then
begin
SetLength(dog, (Length(dog))+1);
i := i + 1;
end;
if ident = '@' then
begin
WriteLn('Importing Owner Name......');
ReadLn(StoredData, dog[i].OwnerName);
WriteLn(dog[i].OwnerName);
end;
if ident = '#' then
begin
WriteLn('Importing Breed...........');
ReadLn(StoredData, dog[i].breed);
WriteLn(dog[i].breed);
end;
if ident = '$' then
begin
WriteLn('Importing Gender..........');
ReadLn(StoredData, dog[i].gender);
WriteLn(dog[i].gender);
end;
if ident = '%' then
begin
WriteLn('Importing Spay/Neut.......');
ReadLn(StoredData, dog[i].spay_neut);
WriteLn(dog[i].spay_neut);
end;
if ident = '^' then
begin
WriteLn('Importing Weights.........');
SetLength(dog[i].weight, (Length(dog[i].weight))+1);
ReadLn(StoredData, (dog[i].weight[o]));
WriteLn(dog[i].weight[o], ' ');
o := o + 1;
end;
if ident = '&' then
begin
WriteLn('Importing BCS.............');
SetLength(dog[i].bcs, (Length(dog[i].bcs))+1);
ReadLn(StoredData, (dog[i].bcs[z]));
WriteLn(dog[i].bcs[z], ' ');
z := z + 1;
end;
end;
until ident = '~';
WriteLn('');
WriteLn('Import Complete...........');
Close(StoredData);
end;
任何信息或建议都会有所帮助!
谢谢,纳特
编辑 - 这是第二只狗在终端中的输出。除了 dogs Weight 和 BCS 之外的所有内容都出来了,然后当我尝试通过添加新狗来编辑 dog 数组时,程序以访问冲突为由退出。
您需要在循环的每次迭代中仔细重新初始化加载过程中的变量:
i := 0;
repeat
o := 0;
z := 0;
SetLength(dog, i+1);
SetLength(dog[i].weight, 0);
SetLength(dog[i].bcs, 0);
...
inc(i);
until...
否则 o
和 z
变量递增到高于 weight 和 bcz 数组上边界的值。
我决定也写一个答案。我已经给出了一个答案,说明了您问题的确切解决方案。但是我觉得我需要解释一下,您使用的方法从一开始就不是最佳的……这不是使用 Pascal 方言的方式。
让我们开始吧。
首先。 Pascal 开发人员通常在用户定义类型的名称前使用 T
:我重命名了记录声明。这是声明。
type
TDogInformation = record
OwnerName: String;
// other fields...
end;
下一步。我声明了以下变量:
var
fl: file;
RecSize: word; // This variable will be used for fast data access
DI: array of TDogInformation;
i: word;
我以这种方式填充数据,您可以使用任何其他方式。
Setlength(DI, 2);
with DI[0] do
begin
OwnerName := 'First owner';
name := 'First dog';
breed := 'Mixed';
gender := 0;
Setlength(weight, 2);
weight[0] := 56;
weight[1] := 60;
spay_neut := 1;
Setlength(bcs, 1);
bcs[0] := 15;
end;
with DI[1] do
begin
OwnerName := 'Second owner';
name := 'Second dog';
breed := 'Mixed mixed';
gender := 1;
Setlength(weight, 1);
weight[0] := 64;
spay_neut := 1;
Setlength(bcs, 12);
bcs[0] := 16;
bcs[1] := 18;
end;
现在我们进行数据的快速写入。整个过程只需要几行代码。
AssignFile(fl, 'b:\asd.txt');
ReWrite(fl);
for i := 0 to High(DI) do
begin
RecSize := SizeOf(DI[i]); //<--We calculate and keep the buffer size
BlockWrite(fl, RecSize, 2); //<--and write it in the file to simlify reading
BlockWrite(fl, DI[i], RecSize);//<--Now we write the record at once.
end;
CloseFile(fl);
下面是快速阅读。
AssignFile(fl, 'b:\asd.txt');
SetLength(DI, 0);//line is compulsory. We reinitialize DI
Reset(fl);
i := 0;
repeat
Setlength(DI, i+1);
BlockRead(fl, RecSize, SizeOf(RecSize) { =2 as it is a word });
//^ You will get the record size by reading the word variable first
BlockRead(fl, DI[i], RecSize); //Now read the record using its fetched size
WriteLn(DI[i].OwnerName);//output the records' data
Inc(i);
until Eof(fl);
CloseFile(fl);
ReadLn;
就是这样。您确实需要解析文本数据。最后。有一些技术允许一次写入整个集合(例如,使用 TStream/TMemoryStream/TFileStream)而无需任何解析 and/or setting/fetching 单个记录的长度。