Чтение файла в FreePascal - PullRequest
       31

Чтение файла в FreePascal

4 голосов
/ 23 марта 2012

У меня есть текстовый файл с указанной структурой, а именно (для каждой строки): символ, пробел, символ, пробел, двойное значение, конец строки. Например

q w 1.23
e r 4.56
t y 7.89

Как правильно «извлечь» эти значения в Free Pascal?

Ответы [ 3 ]

5 голосов
/ 23 марта 2012

FreePascal имеет функцию SScanF в SysUtils (вы можете узнать это на других языках ..)

Я изменил пример 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.
2 голосов
/ 23 марта 2012

Вы можете использовать класс 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.
1 голос
/ 23 марта 2012

Допустим, нам интересно прочитать файл, предоставленный аргументом командной строки после переключателя, содержащий веса подстановки для символов.

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, так как не хочу. или, чтобы быть разделителем слов.

...