Dec 232017
 
Various file routines written in TP 5.5 using OOP technology. Full source code is included. Very nice for beginers to OOP.
File PDIR10.ZIP from The Programmer’s Corner in
Category Pascal Source Code
Various file routines written in TP 5.5 using OOP technology. Full source code is included. Very nice for beginers to OOP.
File Name File Size Zip Size Zip Type
PDIR.DOC 20882 5963 deflated
PDIR.PAS 10457 2345 deflated
PFF.DOC 382 227 deflated
PFF.PAS 1202 553 deflated

Download File PDIR10.ZIP Here

Contents of the PDIR.DOC file


PDir v1.0, 18 Aug 89

Palcic Directory Routines
-------------------------

Matthew J. Palcic
MJP Enterprises
1030 Dayton-Yellow Springs Rd.
Xenia, OH 45385-9508

The routines in PDir are Copyright (C) 1989 by Matthew J. Palcic.
The code is public domain, but a donation would be greatly appreciated.
Any suggestions for modifications/additions to the source code are
welcome. However, the source code is to be distributed only in its
original, unmodified form. MJP Enterprises reserves the rights to all
code and documentation included with PDir. MJP Enterprises and Matthew
J. Palcic shall not be held responsible for any damages resulting from
the use of this code. No warranty is offered (express or written) for
the performance or accuracy of the documentation and source code. If
you plan to use PDir for a distribution program (shareware, public
domain or commercial) please inform Matthew Palcic at the address above.
I'd like to know who's using my code and for what purposes.

PDir was developed using Turbo Pascal 5.5 on a 286 machine running
MS-DOS 4.01. Requires the Objects unit found on the Turbo Pascal 5.5
distribution disks.

The routines in the PDir unit are based almost entirely on the
object-oriented extensions in Turbo Pascal 5.5. The user should be
familiar with the stream, node and list types found in the Objects unit
provided in OOPDEMOS.ARC found on the Turbo 5.5 distribution disks. Also
an understanding of recursive calls is helpful but not required to use
the routines. Even though there are many methods which may not be used
in a program, the smart linker will eliminate all unused methods at
compile time. The data elements in the objects should not be directly
accessed in a program; the methods defined for each object should be
sufficient forms of access to the data elements. If these routines do
not fill a need, define a descendant object type that inherits all the
other routines and adds the function you need. It is strongly
recommended that the user employ these objects as dynamic (using their
Ptr counterparts) rather than static. This offers much more flexibility
than the static routines can offer.

Throughout this documentation a compact notation is used to
describe any elements or routines from other units. Turbo Pascal allows
a unit specifier to precede any items in the unit to prevent ambiguity
(such two procedures having the same name.)

An example:

PDir defines a routine Rename that calls the Dos unit's routine
Rename. Calling Rename does not clearly call either version so
PDir.Rename and Dos.Rename explicitly call one or the other.

This notation is also used to specify where a routine, variable, etc.
originates. Rather than saying 'The NameStr type found in the Dos unit'
the documentation would read Dos.NameStr. Sufficient documentation is
found in the Turbo Pascal manual such that they need not be explained
here. The examples will build on other methods in the object for
clarity.


FileStr
-------

FileStr is used to combine a filename into one string rather than
the separate Dos.NameStr and Dos.ExtStr. FileStr includes the '.'
before the extension.


PDir.BaseEntry
--------------

BaseEntry is the ancestor to FileEntry and DirEntry described
later. This contains all of the information found in a Dos.SearchRec
except for SearchRec.Fill. Fill is not used by any of the routines in
PDir or any other program I've seen for that matter. The data elements
contained in BaseEntry include the Name, Attribute, Size and Time
(stored in standard packed format; see PackTime/UnpackTime). The
function methods return the values stored in memory and may not reflect
current data if the disk was updated after creating the object.


constructor BaseEntry.Init;
---------------------------

Dummy constructor routine meant to be overridden by descendant
types.


destructor BaseEntry.Done; virtual;
-----------------------------------

Dummy destructor routine meant to be overridden by descendant
types.


procedure BaseEntry.ConvertRec(S: SearchRec);
---------------------------------------------

ConvertRec converts Dos.SearchRec 'S' into the data elements needed
in BaseEntry. SearchRec.Fill is ignored.

uses Dos;
procedure GetFirstFile;
var
DirInfo: Dos.SearchRec;
FirstFile: BaseEntry;
begin
ChDir('C:\');
FirstFile.Init; { Must call the constructor }
FindFirst('*.*',Dos.Archive,DirInfo);
FirstFile.ConvertRec(DirInfo);
...

function BaseEntry.FileName: NameStr; virtual;
----------------------------------------------

FileName returns the entire filename including the extension, which
is often more useful than using FileName+FileExt. This is a virtual
routine, so a descendant type may define FileName to return only the
filename without the extension.

WriteLn('Filename: ',FirstFile.FileName);

Result:
Filename: AUTOEXEC.BAT


function BaseEntry.FileExt: ExtStr;
-----------------------------------

FileExt returns only the extension of the file, without the period.
This method is virtual, so descendant types may define FileExt to
include the period.

WriteLn('Extension only: ',FirstFile.FileExt);

Result:
Extension only: BAT


function BaseEntry.FullName: PathStr; virtual;
----------------------------------------------

FullName returns the same string as BaseEntry.FileName. It is
virtual so that descendant types may include a FilePath data element and
define FullName to return the FilePath and FileName in one string.


function BaseEntry.FileTime: Longint; virtual;
----------------------------------------------

FileTime returns the file time in standard packed format (Longint).
See Dos.PackTime and Dos.UnpackTime and the Dos.DateTime record. It is
virtual to allow descendant types to return current data from the disk
on every call, rather than returning values stored in the object. This
would allow other routines to update a file and let FileTime return the
new filetime.

var
DT: DateTime;
begin
UnpackTime(FirstFile.FileTime,DT);
WriteLn(FirstFile.FullName);
WriteLn(Month:2,'/',Day:2,'/',(Year - 1900):2);
WriteLn(Hour:2,':',Min:2,':',Sec:2);
end;

Result:
AUTOEXEC.BAT
11/13/88
12:35:26


function BaseEntry.FileAttr: AttrType; virtual;
-----------------------------------------------

FileAttr returns the attribute of the file. Constants describing
the bit fields of the returned AttrType are described under 'Files,
Attributes, Constants'. This is virtual to allow real-time checking of
the file attribute (especially useful for file sharing).


function BaseEntry.FileSize: Longint; virtual;
----------------------------------------------

FileSize returns the total size (in bytes) of the file. This is
virtual to allow the FileSize to return the current size, rather than
the size in memory.

function BaseEntry.IsDirectory: Boolean;
----------------------------------------

Returns True if the file attribute contains the Directory bit.


constructor BaseEntry.Load(var S: Stream);
------------------------------------------

Load will read in an object of type BaseEntry from a stream. This
is a constructor and is a suitable replacement for using BaseEntry.Init.

var
Strm: PDir.DirStream;
begin
Strm.Init('C:\FILE.DAT',SOpen);
FirstFile.Load(Strm);
Strm.Done;
end;


procedure BaseEntry.Store(var S: Stream); virtual;
--------------------------------------------------

Store will write the data in a BaseEntry instance to a stream.

var
Strm: PDir.DirStream;
begin
Strm.Init('C:\FILE.DAT',SCreate);
FirstFile.Store(Strm);
Strm.Done;
end;


PDir.FileEntry
--------------

A descendant of BaseEntry offering methods to change any of the
elements in BaseEntry. No new data elements are defined.


constructor FileEntry.Init;
---------------------------

Initializes the data elements to acceptable empty values to prevent
impossible dates, times, filenames, etc.


destructor FileEntry.Done; virtual;
-----------------------------------

Dummy destructor that calls BaseEntry.Done;


procedure FileEntry.ForceExt(E:ExtStr);
---------------------------------------

ForceExt accepts a file extension (without the period) and forces
it on the filename. This is useful for changing a .DAT file to a .BAK
file, etc. This calls Rename to change the name of the file on disk and
in memory.

...
WriteLn('Old name: ',FileEntry.FullName);
FileEntry.ForceExt('ZIP');
WriteLn('New name: ',FileEntry.FullName);
...


Old name: GARBAGE.ARC
New name: GARBAGE.ZIP


procedure FileEntry.ChangeName(P:PathStr); virtual;
---------------------------------------------------

ChangeName will only change the filename in memory. Rename should
be used to change the name on disk.


procedure FileEntry.ChangePath(P:PathStr); virtual;
---------------------------------------------------

ChangePath performs the same function as ChangeName. Descendant
types should declare ChangePath to change the path and the filename.


procedure FileEntry.ChangeTime(T:Longint); virtual;
---------------------------------------------------

ChangeTime only changes the time in memory. SetTime should be used
to update the time on disk.


procedure FileEntry.ChangeAttr(A:AttrType); virtual;
----------------------------------------------------

ChangeAttr only changes the attribute in memory. SetAttr should be
used to change the attribute on disk.


function FileEntry.Erase: Boolean; virtual;
-----------------------------------

Erase will remove the file from the directory. If the file is
locked or has read-only status the file will not be deleted. Descendant
types could define Erase to set the attribute to allow deletion
regardless of the current attribute. Erase returns true if the file was
deleted.


function FileEntry.Rename(NewName:PathStr): Boolean; virtual;
-------------------------------------------------------------

Rename changes the name of the file on disk. Returns true if the
rename was successful. Also calls ChangePath to change the name in
memory.


function FileEntry.ResetTime: Boolean;
--------------------------------------

ResetTime resets the filetime on disk to that stored in memory.
This can be used for programs that update a file and need to reset the
original time. An example might be appending information to a text file
and resetting the time so the file appears unmodified.


function FileEntry.ResetAttr: Boolean;
--------------------------------------

ResetAttr is similar to FileEntry.ResetTime except it deals with
the file attribute.


function FileEntry.SetTime(T:Longint): Boolean; virtual;
--------------------------------------------------------

SetTime updates the time of the file on disk without changing the
time in memory. Descendant types could make a call to FileEntry.SetTime
followed by a call to FileEntry.ChangeTime to update both, as this
method is virtual. SetTime returns true of the time was successfully
changed.


function FileEntry.SetAttr(A:AttrType): Boolean; virtual;
---------------------------------------------------------

SetAttr is similar to FileEntry.SetTime except it deals with the
file attribute.


constructor FileEntry.Load(var S: Stream);
------------------------------------------

Load calls BaseEntry.Load. No data elements were introduced in
FileEntry so no other data needs to be read from the stream.


procedure FileEntry.Store(var S: Stream); virtual;
--------------------------------------------------

Store calls BaseEntry.Store. No data elements were introduced in
FileEntry so no other data needs to be stored on the stream.


PDir.DirEntry
-------------

DirEntry is a descendant of PDir.FileEntry. It introduces one new
data element: DirEntries. DirEntries is of type Objects.List. It is to
be used as a list of PDir.DirEntry for recursively searching
subdirectories or searching just one directory. This allows for easy
file management and directory management. The order of entries in the
list can not be assumed to contain files then directories, or vice
versa. The entries are to be handled in an arbitrary manner. However,
the FindDirectories routine will append files to the list first, then
directories. This is useful for processing all files in a directory
before proceeding to the subdirectories. One technique would be to
Insert any files and Append any directories to the list to maintain a
consistent structure. DirEntry nodes contain the DirEntries element,
where FileEntry nodes do not. To see the data structures used with
DirEntry see DirEntry.FindFiles and DirEntry.FindDirectories.


constructor DirEntry.Init;
--------------------------

Init will call FileEntry.Init and delete the entries in the
DirEntries list. This should not be used as a parameter to New() as
DirEntries may contain uninitialized data immediately after allocation.
This may be called after the object has been allocated to delete the
items from DirEntries and reset the FileEntry information.


constructor DirEntry.Clear;
---------------------------

Clear first clears the DirEntries list and then calls
DirEntry.Init. This should be used as the parameter to a dynamic object
allocation.

var
DP: DirEntryPtr;
...
New(DP,Clear);
...


destructor DirEntry.Done; virtual;
----------------------------------

Done deletes the entries in DirEntries and then calls
FileEntry.Done.


procedure DirEntry.FindFiles(FileSpec: PathStr; Attrib: AttrType);
------------------------------------------------------------------

FindFiles is a front end for the FindFirst and FindNext found in
the System unit. FileSpec can contain wildcards but must not contain a
path; the current directory on the currently logged drive is processed.
FindFiles creates a List of FileEntry nodes for all files in the current
directory that match the parameters. If Attrib includes the Directory
attribute then subdirectory names will be included as normal files in
the list. Those directories will not be recursively scanned for files.
This allows creation of a list that contains files and subdirectories
(stored as normal file entries) without scanning all subdirectories. In
general the Directory attribute would not be passed. The list is stored
in DirEntry.FileList.

Example for DirEntry.FindFiles:

procedure GetSourceFileList;
var
SourceDir: DirEntryPtr;
begin
ChDir('C:\PROGRAM\SOURCE');
New(SourceDir,Clear);
SourceDir^.FindFiles('*.PAS',Dos.Archive);
end;

SourceDir^.FileList might contain:


DYNABOOT.PASDBOBJ.PAS DBEDITOR.PAS






procedure DirEntry.FindDirectories(FileSpec: PathStr; Attrib: AttrType);
------------------------------------------------------------------------

FindDirectories is an extended version of FindFiles that
recursively searches subdirectories. FindDirectories calls FindFiles if
FileSpec is not empty. The current directory is the first directory
processed and will be returned to when FindDirectories ends. This
routine can be used to create a tree of the drive if FileSpec is empty.
The data structure created by FindDirectories is shown by the following
diagram of a root directory containing several files and \DOS:


AUTOEXEC.BATCONFIG.SYS DOS





ASSIGN.COM BACKUP.COM CHKDSK.COM





A simple shell of a program to process the data structure created by
FindDirectories might be:

procedure ProcessDir(D: DirEntryPtr);
var
DirPtr : DirEntryPtr;
begin
DirPtr := DirEntryPtr(D^.DirEntries.First);
while DirPtr <> nil do
begin
if DirPtr^.IsDirectory then
ProcessDir(DirPtr); {recursively process subdirectories}
else
{process file};
DirPtr := DirEntryPtr(D^.DirEntries.Next(DirPtr));
end;
end;


constructor DirEntries.Load(var S: Stream);
-------------------------------------------

Load calls FileEntry.Load and then calls DirEntries.Load. This is
also a constructor and can be a suitable replacement for Clear or Init.


procedure DirEntries.Store(var S: Stream); virtual;
----------------------------------------

Store calls FileEntry.Store and then calls DirEntries.Store.


PDir.DirStream
--------------

DirStream is a descendant of Objects.DosStream used to store
BaseEntry, FileEntry and DirEntry objects on disk. The only method is
RegisterTypes, but it should never be called by a program; RegisterTypes
is called by the Stream routines.

Example:

program WriteStructure;
var
DP: DirEntryPtr;
DS: DirStream;
begin
ChDir('C:\');
New(DP,Clear);
DP^.FindDirectories('*.ZIP',AnyFile);
DS.Init('C:\ZIPFILES.DAT',SCreate);
DP^.Store(DS);
DS.Done;
Dispose(DP,Done);
end;


function PDir.ReadString(var S: Stream): String;
------------------------------------------------

ReadString returns a string from the current position in Stream S.


procedure PDir.WriteString(var S: Stream; Str: String);
-------------------------------------------------------

WriteString will write the string Str to the Stream S. Only the
characters that belong to the string will be written. Ordinarily, a
definition like:

TYPE
Str80: String[80]

results in any variable of type Str80 requiring 81 bytes of storage (80
bytes plus one byte to store the length). Writing a Str80 with
SizeOf(Str80) would always write 81 bytes to the stream. WriteString
only writes (Length(Str) + 1) bytes to the stream, keeping the stream as
garbage free as is possible.


function PDir.ExtensionPos(FName : PathStr): Word;
--------------------------------------------------

ExtensionPos is used internally by PDir to find the position of the
period in a PathStr. This can be useful for any routines that may need
to manipulate a file extension based on its position in the PathStr.


function PDir.CurDir: PathStr;
------------------------------

CurDir acts as a front end to the System.GetDir procedure. CurDir
assumes that the current drive (drive 0 according to GetDir) is the
drive requested. Ordinarily a variable is needed as well as a call to
GetDir, followed by the code that needs the current directory. CurDir
can be used to pass the current directory to a routine in one shot.

Example:

...
WriteLn('Current directory: ',CurDir);
...


END.


 December 23, 2017  Add comments

Leave a Reply