在FreePascal中读取文件

时间:2012-03-22 22:53:11

标签: file pascal freepascal fpc

我有一个具有指定结构的文本文件,即(对于每一行):char,space,char,space,double value,endline。例如

q w 1.23
e r 4.56
t y 7.89

在Free Pascal中“提取”这些值的正确方法是什么?

3 个答案:

答案 0 :(得分:5)

FreePascal在SysUtils中具有SScanF功能(您可能知道是否来自其他语言..)

我修改了RRUZ的示例以显示如何使用它。

uses SysUtils;

type
  TData=object
    Val1 ,
    Val2 : String;
    Val3 : Double;
  end;

procedure ProcessFile(aFileName:String);
var
  F     : Text;
  LData : TData;
  Line  : String;
begin
  DecimalSeparator:='.';
  AssignFile(F,aFileName);
  Reset(F);
  while not eof(F) do
  begin
    ReadLn(F,Line);
    SScanf(Line,'%s %s %f',[@LData.Val1,@LData.Val2,@LData.Val3]);

    //do something with the data
    WriteLn(LData.Val1);
    WriteLn(LData.Val2);
    WriteLn(LData.Val3);
  end;
end;

begin
  ProcessFile('C:\Bar\Foo\Data.txt');
  Writeln('Press Enter to exit');
  Readln;
end.

答案 1 :(得分:2)

您可以使用TStringList类加载文件,使用DelimitedText属性将值拆分到另一个TStringList上,然后将值存储在记录中。

检查此样本

{$mode objfpc}{$H+}

uses
  Classes, SysUtils;

{$R *.res}

type
  TData=record
    Val1: Char;
    Val2: Char;
    Val3: Double;
  end;

procedure ProcessFile;
var
  LFile  : TStringList;
  Line   : TStringList;
  i      : Integer;
  LData  : TData;
  LFormat: TFormatSettings;
begin
  //set the propert format for the foat values
  LFormat:=DefaultFormatSettings;
  LFormat.DecimalSeparator:='.';

  LFile:=TStringList.Create;
  Line :=TStringList.Create;
  try
   //load the file
   LFile.LoadFromFile('C:\Bar\Foo\Data.txt');
   Line.Delimiter:=' ';
    for i:=0 to LFile.Count-1 do
    begin
      //read the line and split the result
      Line.DelimitedText:=LFile[i];
      //some basic check
      if Line.Count  <> 3 then raise Exception.Create('Wrong data length');

      //you can add additional check here    
      LData.Val1:=Line[0][3]; 
      LData.Val2:=Line[1][4];
      LData.Val3:=StrToFloat(Line[2],LFormat);

      //do something with the data
      WriteLn(LData.Val1);
      WriteLn(LData.Val2);
      WriteLn(LData.Val3);
    end;
  finally
    Line.Free;
    LFile.Free;
  end;
end;

begin
 try
    ProcessFile;
 except on E:Exception do Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;
end.

答案 2 :(得分:1)

假设我们有兴趣读取一个文件,该文件由切换后的命令行参数提供,包含字符的替换权重。

program WeightFileRead;
uses SysUtils, StrUtils;
var
   MyFile : TextFile;
   FirstChar, SecondChar, DummyChar : Char;
   Weight : Double;
begin
   if GetCmdLineArg ('editweights', StdSwitchChars) = ''
   then begin
      WriteLn ('Syntax: WeightFileRead -editweights filename'); exit
   end;
   AssignFile (MyFile, GetCmdLineArg ('editweights', StdSwitchChars));
   Reset (MyFile);
   try
      while not EOF (MyFile) do
      begin
         ReadLn (MyFile, FirstChar, DummyChar, SecondChar, Weight);
         WriteLn ('A: ', FirstChar, '; B: ', SecondChar, '; W: ', Weight:0:1);
      end
   finally
      CloseFile (MyFile)
   end
end.

在更一般的设置中,当前两个条目可以是更长的字符串时,我们可以使用ExtractWord在字符串中找到n以空格分隔的单词,(或ExtractSubstr将几个空格一起视为引入空单词,并将第三个空格转换为数字。

program WeightFileRead2;
uses SysUtils, StrUtils;
var
   MyFile : TextFile;
   FileLine : String;
begin
   if GetCmdLineArg ('editweights', StdSwitchChars) = ''
   then begin
      WriteLn ('Syntax: WeightFileRead -editweights filename'); exit
   end;
   AssignFile (MyFile, GetCmdLineArg ('editweights', StdSwitchChars));
   Reset (MyFile);
   try
      while not EOF (MyFile) do
      begin
         ReadLn (MyFile, FileLine);
         WriteLn ('A: ', ExtractWord (1, FileLine, [' ']),
                  '; B: ', ExtractWord (2, FileLine, [' ']),
                  '; W: ', StrToFloat (ExtractWord (3, FileLine, [' '])):0:1);
      end
   finally
      CloseFile (MyFile)
   end
end.

注意我使用[' ']而不是StdWordDelims,因为我不想要。或者,成为一个单词分隔符。