pascal跳过文件,虽然它不是空的

时间:2018-01-04 14:19:59

标签: pascal

我正在尝试使用pascal从txt文件中读取一些数据。 当我使用while循环继续执行操作而文件尚未结束时,pascal忽略while循环并继续执行程序结束。 我真的不知道为什么会发生这种情况我正在使用的文件是.txt文件,这肯定不是空的!

下的代码
program Wiki_Lezen;

{$mode objfpc}

 TYPE wikiNew=RECORD
  naam,omschrijving:string;
 END;

  var f: file of wikiNew;
  var bestandsNaam:string;
  var wiki:wikiNew;
  var teller:integer;



begin

  writeln('Geef een bestandsnaam op');
  readln(bestandsNaam);
  ASSIGN(f,bestandsNaam);
  RESET(f);

  while not EOF(f) do
  begin
     read(f,wiki);
     writeln('wikinaam: ', wiki.naam);
     writeln('Geef een omschrijving voor wiki');
     readln(wiki.omschrijving);
     write(f,wiki);
  end;

  CLOSE(f);

  writeln;
  writeln('Om het programma te stoppen druk op <ENTER>');
  readln();
end.  

2 个答案:

答案 0 :(得分:1)

wikinew记录是512字节(两个短串,255个字符+每1个长度字节)。

你的文件是一系列512字节的记录,里面有两条短串吗?或者您是否正在尝试阅读一般文本文件?那不会奏效。 &#34;文件&#34;仅用于恒定大小的数据。

您要查找的文件类型是文本,或者如果不允许,则需要使用char文件。

答案 1 :(得分:0)

更新我已将我的示例代码和此答案的其余部分更新为 按照Marco van de Voort的评论建议使用ShortStrings,我有义务这样做。使用我更新的代码, 它创建和读取数据文件,我无法重现您的问题。 该代码将3 wiki条记录写入文件并成功读回。

program ReadTextFileTestShortString;

{$mode objfpc}  //{$H+}

uses
  SysUtils;

 type wikiNew = record
  naam,omschrijving:string;
 end;

  var f : file of wikiNew;
  var bestandsNaam:string;
  var wiki:wikiNew;
  var teller:integer;
begin
  // First construct a data file name, based on the executable's name
  bestandsNaam := ExtractFilePath(ParamStr(0)) + ' Wiki.Dat';

  //  Next, generate the file
  Assign(f, bestandsNaam);
  Rewrite(f);
  for teller := 1 to 3 do begin
    wiki.naam := 'Name' + IntToStr(teller);
    wiki.omschrijving := 'Omschrijving' + IntToStr(teller);
    write(f, wiki);
  end;

  //  Now, read the file
  Reset(f);
  while not Eof(f) do begin
    read(f, wiki);
    writeln('Name: ', wiki.naam);
    writeln('Description: ', wiki.omschrijving);
  end;
  Close(f);
  readln;

end.

我将不得不留给你调查为什么你显然会有所不同 你的代码的行为。也许&#34;用户&#34;没有输入文件名 包括绝对路径,因此读取文件的不同版本 你假设的那个。

顺便说一句,这个答案的先前版本是基于这样的假设 你正在使用所谓的&#34;巨大的&#34;字符串并收到了投票。这是 合理的,但我希望现在可以删除投票。

我不明白你是如何编写代码的。作为@Tom Brunberg 在注释中注明,FPC中的字符串是引用类型,您无法声明 file of引用类型。当我尝试编译代码时,我得到了

  

ReadFileTest.pas(12,26)错误:输入的文件不能包含引用计数类型。

string的情况下,FPC不允许包含file of记录的原因 字符串非常明显:字符串可以包含任意序列 字符长度最大为2Gb,因此在读取文件时,RTL将无法使用 知道一个字符串字段的结束位置以及下一个字段或记录的开始。从历史上看,记录的Pascal文件总是基于记录 具有固定长度,在编译时已知,因此编写过程 文件记录的一个实例只涉及写一个图像 内存中的记录到文件中。

因此,如果要存储包含字符串字段的记录,则最直截了当   这样做的方法是使用text文件并存储记录的各个字段   作为单独的行,例如,如下:

代码:

uses
  SysUtils;

 type wikiNew = record
  naam,omschrijving:string;
 end;

  var f : Text;  // declares a text file
  var bestandsNaam:string;
  var wiki:wikiNew;
  var teller:integer;
begin
  //  First construct a data file name, based on the executable's name
  //  This is to avoid the user having to type the file name correctly
  //  and to ensure that the file name includes an absolute path

  bestandsNaam := ExtractFilePath(ParamStr(0)) + ' Wiki.Dat';


  //  Next, generate the file
  Assign(f, bestandsNaam);
  Rewrite(f);
  for teller := 1 to 3 do begin
    wiki.naam := 'Name' + IntToStr(teller);
    wiki.omschrijving := 'Omschrijving' + IntToStr(teller);
    writeln(f, wiki.naam);
    writeln(f, wiki.omschrijving);
  end;

  //  Now, read the file
  Reset(f);
  while not Eof(f) do begin
    readln(f, wiki.naam);
    readln(f, wiki.omschrijving);
    writeln('Name: ', wiki.naam);
    writeln('Description: ', wiki.omschrijving);
  end;
  Close(f);
  readln;

end.

因此,请勿尝试混合使用Pascal file of [record]文件和Text文件。 file of [record]文件在正确使用后,可以正常工作,但需要基于固定长度的记录,而file of wikiNew必然不是,因为记录定义包含string个字段。 / p>

顺便说一下,有一个评论说明了#&#34;启动阅读&#34;可能是必要的。它不是,并且永远不需要正确编写的Pascal代码。