Dateinamen & Pfade

Gerade bei Studenten erfreuen sich die Computer der ATARI ST-Serie allergrösster Beliebtheit. Um Programmieraufgaben zu lösen, greifen die Studenten meist auf die im Studium erlernte Pascal-Sprache zurück. Für den ATARI ST gibt es ja dankenswerterweise eine tolle PASCAL-Implementation der Firma CCD, allseits als ST PASCAL+ bekannt. Mit ihr kann (wenn der Programmierer das nötige Know-How besitzt) auf relativ einfache Art ein voll GEM-unterstütztes Programm erstellt werden.

Leider hört das saubere Programmieren meist bei der Pfadhandhabung auf. Wie oft habe ich schon erlebt, daß ein Programm auf Festplatte nicht installierbar war. weil absolute Pfade im Programm vorgegeben waren. Oft muß man sich auch aus oberster Directory-Ebene in den Ordner des geladenen Programms durchklicken, um an die dort abgelegten Dateien zu kommen. manchmal sogar jedesmal nach Aufruf der Fileselectorbox. Um nun jedem Programmierer das Erstellen von sauberen GEM-Programmen zu erleichtern, habe ich einige Routinen entworfen, die schon oft ihren Einsatz in Simulations- und Rechenprogrammen gefunden haben. Sie sind verwendbar für jede Art von Programm, sei es ein Zeichenprogramm oder eine Dateiverwaltung.

Im einzelnen werden folgende Aufgaben vereinfacht:

Jeder Pascal-Anwender sollte jetzt schnellstens das Listing eintippen und der Dinge harren. die da passieren (zum Testen der neuen Funktionen wurde ein kurzes Demo-Programm hinzugefügt). Nach Starten des Programms wird zuerst der aktuelle Pfad bei Programmstart ermittelt und auf dem Bildschirm ausgegeben. Hiernach erscheint eine Dialogbox. in der der werte Leser eine Datei (unter einem beliebigen Pfad) auswählen sollte, um das Können des Programms auf die Probe zu stellen. Hat nun der User (aus Versehen natürlich) nicht dummerweise auf den Abbruch-Button geklickt, erscheint jetzt der komplette Pfad mit der ausgewählten Datei auf dem Bildschirm. Weiterhin wird der Dateiname mit Pfad ohne Suffix sow ie nur der Dateiname ohne Suffix und der Suffix selbst ausgegeben.

Jeder Programmierer, der etwas Mitleid mit uns armen Festplattenbesitzern hat. sollte nun immer diese Routinen zur Dateiauswahl in seine Programme einbinden (der Klick-Finger meiner rechten Hand wird es danken).

Aufbau des Programms

In der Funktion exist_file wird nachgeschaut, ob der angegebene Pfad mit angehängtem Dateinamen existiert. Ist er vorhanden, wird ein TRUE zurückgeliefert. ansonsten ein FALSE. Zum Nachschauen wird die Funktion fsfirst des GEMDOS benutzt. Sie sucht auf dem Datenträger nach dem ersten Auftauchen einer Datei, welche die angegebenen Bedingungen (bei uns der vollständige Dateipfad mit zugehörigem Dateinamen) erfüllt. Wird anstatt des kompletten Pfades mit Dateinamen nur ein Pattern (z.B.: A:*.*) vorgegeben. wird die erste Datei, die das Muster erfüllt, gesucht. Deshalb findet diese Routine auch hauptsächlich zum Einlesen des Directories Verwendung.

Als zweites soll die Prozedur get_akt_path genannt werden. die den aktuellen Pfad ermittelt. Dies geschieht mit der GEMDOS-Routine getdir. Leider beinhaltet dieser Pfad nicht die Kennzeichnung des aktuellen Laufwerks. Oft verzichten die Programmierer auf das Einfügen des Laufwerksnamens, was man in der Fileselectorbox erkennen kann. Dort beginnt das Pfadmuster (mit INDEX bezeichnet) direkt mit einem Backslash (z.B.: \DEMO*.*). Dies ist nicht anwenderfreundlich, da der Benutzer insbesondere bei Festplattenbenutzung so nicht weiß, auf welcher Partition er jetzt Unheil anrichtet (sprich Dateioperationen ausführt). Deshalb muß der Laufwerksnamen noch mit der Routine dgetdrv ermittelt und dem Pfad vorangestellt werden.

Die dritte wichtige Routine ist die set_path-Funktion. Sie ruft die Routine get_new_path_and_filename auf und dient nur zur Kommunikation mit dem Benutzer. Es wird die Fileselectorbox auf dem Bildschirm dargestellt und vom Betriebssystem verwaltet. Nach Anklicken von OK werden die Einstellungen der Box übernommen und zum aufrufenden Programm zurückgekehrt. Bei Anklicken von Abbruch erfolgt die Rückkehr ohne Übernahme der aktuellen Einstellungen. Anklicken von OK liefert TRUE. Anklicken von Abbruch FALSE zurück.

Als letztes soll die Routine cut_suffix besprochen werden. Sie dient zum Entfernen des Suffixes eines Dateipfades. Dies ist besonders nützlich, wenn ein fester Suffix vom Programm vorgegeben werden soll (z.B. bei DEGAS je nach Auflösung z.B. .PI3) und dieser vom Anwender nicht geändert werden darf, da die betreffende Datei sonst vom Programm nicht mehr wiedergefunden werden kann. Ein weiterer Einsatzzweck ist gegeben. wenn nach Eingabe eines Dateinamens mehrere Dateien mit verschiedenem Suffix abgelegt werden müssen (z.B. die verschiedenen Dateien, die beim Anlegen einer Datenbank mit ADIMENS geschrieben werden müssen). Übergeben werden muß der Pfad (mit Dateinamen). und zurückgeliefert werden der Pfad mit Dateinamen. aber ohne Suffix, nur der Dateinamen (also ohne Pfad und ohne Suffix) und extra der Suffix. Da auch der übergebene Pfad mit Dateinamen von der Routine verändert wird (Suffix wird entfernt), sollte der Aufruf nur mit einer Kopie der verwendeten Pfad-Variablen geschehen.

{=================================================
 Routinen für das Dateihandling mit ST Pascal+ 
 auf ATARI ST von Matthias Baldauf 
 (c) MAXON Computer GmbH 1990 
 vom 15.10.1989
=================================================}

program DATEIHANDLING;

{--- Konstantendefinition ---}

const
    {$I o:TRIXCONS.PAS}
    {$I o:GEMCONST.PAS}

{--- Typ-Vereinbarungen ---}
type
    {$I o:TRIXTYPE.PAS}
    {$I o:GEMTYPE.PAS}
    DatNameType = string[150];

{--- Variablendeklarationen ---}
var
    dummy:boolean;
    dateipfad,dateiname,suffix,name:DatNameType; 
    a:char;

{--- Prozedurteil ---}
    {$I o:TRIXSUBS.PAS}
    {$1 o:GEMSUBS.PAS}

{------------------------------------------------
 Nachschauen, ob Datei mit Pfad vorhanden ist
 -----------------------------------------------}
function exist_file(dateiname:DatNameType): boolean;
    var handle:integer; 
        cstr:Cstring; 
    function fsfirst(var dateiname:Cstring;attr:integer):integer;
    gemdos($4e); 
begin
    PtoCstr(dateiname,cstr); 
    handle := fsfirst(cstr,0); 
    if handle < 0 then 
        exist_file := false 
    else
        exist_file := true;
end;

{------------------------------------------------
 Pfad beim Starten des Programms ermitteln
 ------------------------------------------------}
procedure get_akt_path(var path:DatNameType); 
var path_char:Cstring; 
    dummy:integer; 
    function getdir(var path:Cstring;
                    drv:integer):integer;
    gemdos($47);
    function dgetdrv:integer;
    gemdos($19); 
begin
    dummy := getdir(path_char,0); 
    if dummy = 0 then 
        begin
            CtoPstr(path_char,path);
            path := concat(chr(dgetdrv+65),':',path); 
        end
    else { Fehler ! } 
    ;
end;

{------------------------------------------------
 Neuen Pfad/Dateinamen vom Benutzer holen
 -----------------------------------------------}
function get_new_path_and_filename(var pfad, dateiname:DatNameType):boolean; 
var path,name:DatNameType;
    ergebnis:boolean; 
begin
    path := copy(pfad,1,length(pfad)); 
    name := copy(dateiname,1,length(dateiname)); 
    ergebnis := Get_in_file(path,name); 
    if ergebnis then 
        begin
            pfad : = copy(path,1,length(path)); 
            dateiname := copy(name,1,length(name)); 
        end;
    get_new_path_and_filename := ergebnis; 
end;

{------------------------------------------------
 Neuen Pfad holen (Dialog)
 -------------------------
 Hier können eigene Anpassungen vorgenommen
 werden (z.B.: Maus-Zeiger wieder
 sichtbar machen, Hintergrund restaurieren etc.)
 -----------------------------------------------}
function set_path(var path,dateiname:DatNameType):boolean; 
var dummy_bool:boolean; 
begin
    dummy_bool := get_new_path_and_filename(path,dateiname); 
    set_path := dummy_bool; 
end;

{------------------------------------------------
 Routinen zum entfernen der Suffix eines Namens
 -----------------------------------------------}
procedure revers_str(var name:DatNameType); 
var i,len:integer;
    puffer:DatNameType; 
begin
    len := length(name);
    puffer := '';
    for i := len downto 1 do
        puffer := concat(puffer,name[i]); 
    name := puffer;
end;

procedure cut_suffix(var dateiname,name,suffix:DatNameType);
var i:integer; 
begin
    revers_str(dateiname); 
    if pos('\',dateiname) <> 0 then 
        begin
            name := copy(dateiname,1,pos('\', dateiname)-1); 
            delete(dateiname,1,length(name)); 
            revers_str(dateiname); 
            if pos('.',name) <> 0 then 
                begin
                    suffix := copy(name,1,pos('.',name)-1); 
                    revers_str(suffix); 
                end 
            else
                suffix := '';
            revers_str(name); 
            if pos('.',name) <> 0 then
                name := copy(name,1,pos('.',name)-1); 
            dateiname := concat(dateiname,name); 
        end 
    else 
        begin
            revers_str(dateiname);
            if pos('.',dateiname) <> 0 then
                name := copy(name,1,pos('.',name)-1); 
            if pos('.',dateiname) <> 0 then 
                begin
                    suffix := copy(dateiname,1,pos('.', dateiname)-1); 
                    revers_str(suffix); 
                end 
            else
                suffix := '';
        end;
end;

{ ------------------------ Suffix Routinen Ende --}
{==================================================
 Hauptprogramm (DEMO)
==================================================}
begin
    if Init_Gem >= 0 then 
        begin
            Clear_Home;

            get_akt_path(dateipfad); {aktuellen Pfad ermitteln}
            writeln('Pfad bei Programmstart: ',dateipfad);

            writeln;
            writeln('Bitte irgendeine Datei auswählen:'); 
            dateiname := concat(dateipfad,'\DEMO'); { Dateinamen 'basteln' } 
            dateipfad := concat(dateipfad,'\*.*''); { das 'Auswahlpattern' hinzufügen } 
            dummy := set_path(dateipfad,dateiname); { File-Selector-Box aufrufen } 
            if dummy then 
                begin
                    Clear_Home;
                    writeln('Ausgewählte Datei: ',dateiname);

                    dummy := exist_file(dateiname); 
                    if dummy then
                        writeln('+++ Datei existiert +++')
                    else
                        writeln('--- Datei nicht vorhanden —--');

                    cut_suffix(dateiname,name,suffix); 
                    writeln('Dateiname und Pfad ohne Suffix: ', dateiname);
                    writeln('Dateiname ohne Pfad und ohne Suffix: ',name); 
                    writeln('Suffix: ',suffix);
                    writeln;
                    writeln('--- Taste ---');
                    read(a); 
                end 
            else 
                begin
                    Clear_Home;
                    writeln('Sie haben auf ABBRUCH geklickt !!!');
                    writeln;
                    writeln('--- Taste ---');
                    read(a); 
                end;

        Exit_Gam;
    end;
end.

{------------------------------- PROGRAMMENDE ---}

Matthias Baldauf
Aus: ST-Computer 05 / 1990, Seite 92

Links

Copyright-Bestimmungen: siehe Über diese Seite