NORM%IONAACAD.BITNET@cunyvm.cuny.edu ( Norman Walsh) (02/12/91)
In order to write a FileExists() function, I recommend using either the FindFirst method (and make sure it's a FILE not a directory or something) or a GetFAttr (ditto about making sure it's a file) rather than trying to open the file. Too many things can go wrong trying to open the file. Your pgm might be out of file handles or, if the file is read-only, you have to diddle with the FileMode variable (make sure you put it back) etc. ndw
pp@wsinti01.info.win.tue.nl (Peter Peters) (02/13/91)
I have forgotten who was the initiator of this finfile message chain :-) but here's my two cents.... What follows is a program that will test the protection/properties of files/directories. I suppose the original question can be answered by extracting the right piece of code. Also a command line switch/pasrameter extraction unit uses-ed by the program is included. ------- Program FaTest; (* check if file attribute of the parameter is set, return doserror 0 to indicate check is ok, doserror 1 if not ok *) Uses Dos, TpOpt; Var S : SearchRec; FileAttr : Byte; FileName : String; Procedure ProcessParameters; Var Par : Char; Begin Repeat Par := Getopt( 'rRhHsSvVdDaAfF' ); Case UpCase(Par) Of 'R' : FileAttr := FileAttr Or ReadOnly; 'H' : FileAttr := FileAttr Or Hidden; 'S' : FileAttr := FileAttr Or SysFile; 'V' : FileAttr := FileAttr Or VolumeId; 'D' : FileAttr := FileAttr Or Directory; 'A' : FileAttr := FileAttr Or Archive; 'F' : FileAttr := FileAttr Or (AnyFile And (Not Directory)); '?' : Halt(1); End; Until Par = EofChar; FileName := Argv[Optind]; End; Begin FileAttr := 0; ProcessParameters; FindFirst (FileName,AnyFile,S); If (S.Attr And FileAttr) = 0 Then Halt(1); End. ------ And the uses-ed unit : ------ Unit TPOpt; Interface Uses Dos; Const EofChar : Char = ^Z; (* End of file character *) MaxArg = 15; Type ArgRange = 0..MaxArg; Var SwitChar : Char; (* Dos switch character *) OptErr : Word; (* Enable/Disable invalid switch detection *) OptInd : Word; (* Current Argv index *) OptArg : String; (* Argument for switch *) Argv : Array[ArgRange] Of String; (* Array of parameters *) Argc : ArgRange; (* Number of parameters + 1 *) Procedure ResetOptions; (* (Re)Initialise option processing *) Procedure SetEnvOpt ( EnvirOpt : String ); (* Set environment string *) Function GetOpt( Parm : String ) : Char; (* Get a command line switch *) Implementation Var EnvOpt : String; (* Environment variable used as options/parameters *) Init : Boolean; (* Initialisation done/needeed *) Function GetSwitChar : Char; (* Uses undocumented DOS function 37h *) Var Regs : Registers; Begin {getswitchar} Regs.ax := $3700; MsDos (Regs); GetSwitChar := Char(Regs.dl); End {getswitchar}; Procedure SetEnvOpt{( EnvirOpt : String )}; Begin {setenvopt} EnvOpt := EnvirOpt; End {setenvopt}; Function GetWord( Var Options : String ) : String; Var OptS : String; Mn : Byte; Begin {getword} Repeat While (Length(Options) > 0) And (Options[1] = ' ') Do Delete(Options,1,1); Mn := Pos( ' ',Options+' ' ); OptS := Copy( Options, 1, Mn-1 ); Options := Copy( Options, Mn+1, 255 ); Until (Options = '') Or (OptS <> ''); GetWord := OptS; End {getword}; Procedure ResetOptions; Var i : Byte; Options : String; Begin {resetoptions} Argc := 0; Options := GetEnv( EnvOpt ); Repeat OptArg := GetWord( Options ); If OptArg[0] > #0 Then If OptArg[1] = SwitChar Then Begin Argv[Argc] := OptArg; If OptArg <> '' Then Inc( Argc ); End {if}; Until OptArg = ''; For i := 1 To ParamCount Do Begin OptArg := ParamStr(i); If OptArg[0] > #0 Then If OptArg[1] = SwitChar Then Begin Argv[Argc] := OptArg; If OptArg <> '' Then Inc( Argc ); End {if}; End {for}; Options := GetEnv( EnvOpt ); Repeat OptArg := GetWord( Options ); If OptArg[0] > #0 Then If OptArg[1] <> SwitChar Then Begin Argv[Argc] := OptArg; If OptArg <> '' Then Inc( Argc ); End {if}; Until OptArg = ''; For i := 1 To ParamCount Do Begin OptArg := ParamStr(i); If OptArg[0] > #0 Then If OptArg[1] <> SwitChar Then Begin Argv[Argc] := OptArg; If OptArg <> '' Then Inc( Argc ); End {if}; End {for}; For i := Argc To MaxArg Do Argv[i] := ''; Init := False; OptInd := 0; OptArg := ''; End {resetoptions}; Function GetOpt{( Parm : String ) : Char}; Var OptPos : Byte; Begin {getopt} If Init Then ResetOptions; If (Optind < Argc) And (Argv[Optind,1] = SwitChar) Then Begin OptPos := Pos( Argv[Optind,2], Parm ); If OptPos = 0 Then Begin If OptErr > 0 Then Writeln( ^M^J'Invalid switch : ', Copy( Argv[OptInd], 1, 2 ) ); GetOpt := '?'; End {if} Else Begin GetOpt := Argv[Optind,2]; If (OptPos < Length( Parm )) And (Parm[OptPos+1] = ':') Then Begin OptArg := Copy( Argv[OptInd], 3, Length( Argv[OptInd] ) ); If OptArg[1] = '=' Then Delete( OptArg, 1, 1 ); End {if}; End {else}; Inc( OptInd ); End {if} Else GetOpt := EofChar; End {getopt}; Begin {main} SwitChar := GetSwitChar; OptErr := 1; Init := True; EnvOpt := ''; End {main}. ------ Usage could be : (in a batch file) fatest /f %1 if errorlevel 1 goto checkdir echo "file %1 exists goto exit :checkdir fatest /d %1 if errorlevel 1 goto noexist echo "directory %1 exists" goto exit :noexist echo "%1 is not a file or directory" :exit ------ Use this stuff as you like, Mention my name if you redistribute it or use it in a program. -- | Peter Peters | UUCP : pp@win.tue.nl | | Eindhoven University of Technology (TUE) | PHONE : +31-(0)40-474120 | | Dept. of Mathematics and Computer Science | TUE : HG 8.82 / 4120 | | Disclaimer : I said WHAT ??? | VHF : pa0ppe |
CDCKAB%EMUVM1.BITNET@cunyvm.cuny.edu ( Karl Brendel) (04/19/91)
In article <15647@dutrun.UUCP>, winfave@dutrun.uucp (Alexander Verbraeck) wrote: >The FileExists function as posted in the "Cursor On/Off Code Plus" >posting (originating from Dave Sisson) contains a slight but >extremely boresome error, as far as I can see. My first attempt to >write a FileExists function contained the same error, and it took me >quite a while to find it. The original FE routing looked something >like: [...deleted...] >afterward. What's the flaw? Not closing the file in FileExists, which >occupies a DOS file handler when it exists. What's the solution? Either >always closing the file between the {$I-} and {$I+} directives, or >closing it after testing if IOresult reports that the file exists and >THEN closing the file. >I used the first method, resulting in the following function: > >function FileExists(fn:string) : boolean; > >var > f : text; > >begin > {$I-} > assign(f,fn); > reset(f); > close(f); > FileExists:=(IOresult=0); > {$I+} >end; (Alexander Verbraeck's posting provides an opportunity to discuss a FileExists function. My posting should in no way be taken as a criticism of his excellent discussion or of his particular coding.) FileExists functions seem to be enjoying a spurt of popularity on the net for some reason. :) As Alexander Verbraeck has pointed out, some popular FileExists functions may have unexpected results. They may also fail unexpectedly. E.g., if no file handles are available, Reset will fail, and a Reset-based function will return False. (Does one ever want to know if a file exists without caring if it can be opened. Yes. One example is a network semaphore.) Consider the use of FindFirst for a FileExists function. It works without requiring a file handle, and can easily be used to check the existance of directories, volume IDs, etc.: uses DOS; function FileExists(var fn : string; attr : word) : Boolean; var sr : SearchRec; begin {Exists} FindFirst(fn,attr,sr); FileExists := DosError = 0; end; {Exists} If you want this strictly for determining whether "real" files exist, you can drop attr from the parameters and include an appropriate value in the body of the function. +====================================================================+ | Karl Brendel Centers for Disease Control | | Internet: CDCKAB@EMUVM1.BITNET Epidemiology Program Office | | Bitnet: CDCKAB@EMUVM1 Atlanta GA 30093 USA | | Home of Epi Info 5.0 | +====================================================================+