PDA

View Full Version : Zwei Dateien im IFS lesen



Seiten : [1] 2

Hubert
06-06-17, 13:10
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?

Fuerchau
06-06-17, 13:46
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?

Hubert
06-06-17, 14:16
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.

Fuerchau
06-06-17, 14:23
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;

Hubert
07-06-17, 07:42
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.

BenderD
07-06-17, 08:09
... was verbirgt sich bei Dir hinter readline()???

Fuerchau
07-06-17, 08:21
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

Fuerchau
07-06-17, 11:21
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.

BenderD
07-06-17, 11:48
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.