View Full Version : Zwei Dateien im IFS lesen
Hallo zusammen,
ich versuche zwei Dateien im IFS zu lesen. Zunächst erstelle ich über die QSHELL ein Inhaltsverzeichnis des Verzeichnisses in eine Datei. Dann öffne ich diese Datei, um alle Dateien des Verzeichnisses zu verarbeiten.
command = 'ls ''' + %trim(Verzeichnis) + ''' > '+
%trim(lsDateiname);
rc_qzsh = QzshSystem(Command);
lsDatei = fopen(%trim(lsDateiname) : O_RDONLY + O_TEXTDATA);
if lsDatei >= 0;
dow readline(lsDatei: %addr(lsZeile): %size(lsZeile)) >= 0;
DatName = %trim(Verzeichnis) + %trim(lsZeile);
if access(%trim(DatName):F_OK) = 0;
Datei = fopen(%trim(DatName) : O_RDONLY + O_TEXTDATA);
if Datei >= 0;
dow readline(Datei: %addr(Zeile):
%size(Zeile)) >= 0;
Obwohl für Datei und lsDatei unterschiedliche Dateinummern angezeigt werden, liest das Programm zuerst alle Zeilen aus lsDatei und anschließend alle Zeilen aus Datei.
Wie bekomme ich da eine saubere Abgrenzung hin?
Bist du sicher, dass der 2. fopen nicht fehlschlägt?
Hast du in "Verzeichnis" ein "/" am Ende?
Die Programmstruktur ist unvollständig oder soll ich mit die endif's und enddo's denken?
Hallo Baldur,
ja, ich bin sicher, dass der zweite open nicht fehlschlägt.
Hier der (fast) vollständige Code:
Verzeichnis = '/mailing/' + VERCVP + '/';
lsDateiname = %trim(Verzeichnis) + %trim(VERCVP) + '.inh';
command = 'ls ''' + %trim(Verzeichnis) + ''' > '+
%trim(lsDateiname);
rc_qzsh = QzshSystem(Command);
lsDatei = fopen(%trim(lsDateiname) : O_RDONLY + O_TEXTDATA);
if lsDatei >= 0;
dow readline(lsDatei: %addr(lsZeile): %size(lsZeile)) >= 0;
DatName = %trim(Verzeichnis) + %trim(lsZeile);
nDatei = lsZeile;
if access(%trim(DatName):F_OK) = 0;
Datei = fopen(%trim(DatName) : O_RDONLY + O_TEXTDATA);
if Datei >= 0;
dow readline(Datei: %addr(Zeile):
%size(Zeile)) >= 0;
verarbeite den Satz;
enddo;
fclose(Datei);
endif;
endif;
endif;
enddo;
fclose(lsDatei);
endif;
Wie gesagt, das Programm liest in der inneren Schleife zuerst alle Sätze aus lsDatei und anschließend die Sätze aus Datei.
In der äußeren Schleife wird nur einmal gelesen und dann die Datei geschlossen, weil offensichtlich EOF angenommen wird.
Der returnwert des fopen liefert entweder 0 = Open fehlgeschlagen oder <> 0 Open OK zurück.
Die Abfrage >= 0 ist hier fehlerhaft.
Da der sog. Dateipointer als 10I 0 definiert ist (sein sollte), kann auch ein negativer Wert auftreten.
Also:
if lsdate <> 0;
:
if Datei <> 0;
endif;
:
endif;
Scott Klement sagt da was Anderes:
If something goes wrong, and the system is not able to open the file that we requested, it will return a value of -1 instead of a file descriptor.
c eval fd = open(%trimr(path): flags: mode)
c if fd < 0
c goto bomb_out
c endif
Wie dem auch sei, ich bekomme bei beiden Dateiöffnungen einen positiven Wert zurück. Trotzdem werden mit dem File Descriptor "Datei" in der inneren Schleife zuerst die Sätze gelesen, die in der Datei stehen, deren File Descriptor "lsDatei" ist. Danach werden ebenfalls in der inneren Schleife die Daten aus der Datei gelesen, die mit dem File Descriptor "Datei" geöffnet ist. In der äußeren Schleife wird dann nichts mehr gelesen.
... was verbirgt sich bei Dir hinter readline()???
Du verwendest aber die Funktion "fopen"!
"open()" übergibt einen sog. HANDLER, "fopen()" einen sog. POINTER.
Ein HANDLER ist >= 0 oder bei Fehler -1.
Ein POINTER ist NULL (für RPG eben 0) oder <> NULL.
readline() könnte dann "fgets()" sein.
Rainer Ross
07-06-17, 11:03
Hallo,
was hälst Du von der Möglichkeit mit den Directory API's die Files im Verzeichnis zu lesen und dann die jeweilige Datei. Im Feld streamfile ist dann der Dateiname.
ctl-opt main(main) dftactgrp(*no) option(*nounref);
//------------------------------------------------------------------//
// //
// Directory lesen //
// //
//----------------- //
// R.Ross 06.2017 * //
//------------------------------------------------------------------//
// Open-Directory //
//------------------------------------------------------------------//
dcl-pr opendir pointer extproc(*dclcase);
dirname pointer value options(*string);
end-pr;
//------------------------------------------------------------------//
// Read-Directory //
//------------------------------------------------------------------//
dcl-pr readdir pointer extproc(*dclcase);
dir_p pointer value options(*string);
end-pr;
//------------------------------------------------------------------//
// Close-Directory //
//------------------------------------------------------------------//
dcl-pr closedir int(10) extproc(*dclcase);
dirname pointer value options(*string);
end-pr;
//------------------------------------------------------------------//
// Array Directory Data //
//------------------------------------------------------------------//
dcl-s dirent_p pointer; // DirectoryEntryPtr
dcl-ds dsdirent qualified based(dirent_p);
*n char(16);
*n uns(10);
fileno uns(10);
reclen uns(10);
*n int(10);
*n char(08);
nlsinfo char(12);
nlsccsid int(10) overlay(nlsinfo:01);
nlsentry char(02) overlay(nlsinfo:05);
nlslang char(03) overlay(nlsinfo:07);
nlsreser char(03) overlay(nlsinfo:10);
namelen uns(10);
name char(640);
end-ds;
//------------------------------------------------------------------//
// Main //
//------------------------------------------------------------------//
dcl-proc main;
dcl-s directory varchar(256); // Directory
dcl-s file varchar(256); // File
dcl-s streamfile varchar(256); // StreamFile
dcl-s dir_p pointer; // Directory-Pointer
directory = '/home/import/xml';
dir_p = opendir(directory); // Open Directory
if dir_p = *null; // Directory not exist
return;
endif;
dou dirent_p = *null; // Loop ReadDir
dirent_p = readdir(dir_p); // ReadDir
if dirent_p <> *null; // DirEntry exist
file = %str(%addr(dsdirent.name)); // FileName
if file <> '.' and file <> '..';
streamfile = %trim(directory) + '/' + %trim(file);
endif;
endif;
enddo;
closedir(directory); // Close Directory
end-proc;
//------------------------------------------------------------------//
Herzliche Grüße
Rainer Ross
Er hat ja nicht das Problem, das Verzeichnis zu lesen, sondern die gefundenen Dateien in der inneren Schleife zu lesen, da der "fopen" ggf. auch einen negativen Datei-POINTER zurückgeben kann.
readline() könnte dann "fgets()" sein.
readline ist kein IBM API, sondern irgendwo abgetippselt und falsch angewendet. Wahrscheinlich liest das Ding in einen Buffer, scanned nach CR oder LF oder beides. Wenn der Buffer groß genug ist, passiert genau das beschriebene.
D*B
der immer misstrauisch wird, wenn Code in Homöopathischen Dosen geoutet wird und immer wieder feststellt, dass das Problem meist vor dem Bildschirm sitzt.