Arrays Pascal中的FileIO有问题

Arrays Pascal中的FileIO有问题,arrays,file-io,pascal,Arrays,File Io,Pascal,在我的编程入门课程中,我很难为最后一个项目创建一个有效的保存系统。我正试图保存一组狗的记录。每只狗都有一个名字、主人姓名、品种、性别(1和2与是和否相关)、绝育/绝育状态(1和2同样与是和否相关),以及一个存储在记录中的权重和BCS分数数组,所有这些都在整个狗数组的单独索引中绘制。我设置的系统完美地导入了一只狗,但一旦我添加另一只狗进入终端,我就会收到关于访问冲突的错误。我已经亲手执行了很多次,但似乎找不到问题所在。我将在下面附上代码。谢谢 type DogInformation = recor

在我的编程入门课程中,我很难为最后一个项目创建一个有效的保存系统。我正试图保存一组狗的记录。每只狗都有一个名字、主人姓名、品种、性别(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;
任何信息或建议都会有帮助

谢谢,纳特

编辑-这是第二只狗在终端中的输出。除了狗的体重和BCS之外,所有内容都会显示出来,然后当我尝试通过添加一条新狗来编辑狗数组时,程序会以访问冲突为由退出


在循环的每次迭代中,您需要仔细地重新初始化加载过程中的变量:

  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
变量将增加到高于权重和bcz数组上边界的值

我也决定写另一个答案。我已经给出了一个答案,说明了你问题的确切解决办法。但我觉得我需要解释一下,你使用的aproach从一开始就不是最优的。。。这不是帕斯卡方言的使用方式

让我们开始吧

首先。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);

就这些。您确实需要解析文本数据。最后。有一些技术允许一次写入整个集合(例如,使用TStream/TMemoryStream/TFileStream),而无需任何解析和/或设置/获取单个记录的长度。

您是否进行过任何调试以缩小代码中导致访问冲突的部分?
  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;