Thread Dateistruktur überprüfen (2 answers)
Opened by Gast at 2007-02-01 01:50

Dubu
 2007-02-02 23:03
#73908 #73908
User since
2003-08-04
2145 Artikel
ModeratorIn + EditorIn

user image
@oes: Dein Fehler im zweiten Code ist, dass du das $check=0 innerhalb der Schleife stehen hast; damit wird auch bei einem Fehler dein $check beim Einlesen der nächsten Zeile immer wieder zurückgesetzt. Außerdem solltest du beim Auftreten eines Fehlers das Einlesen der Datei abbrechen, der Rest interessiert dann ja nicht mehr, oder?
Außerdem sollten use strict und use warnings selbstverständlich sein.
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use strict;
use warnings;

for my $datafilename (@ARGV) {
   open my $datafh, '<', $datafilename or die "cannot open $datafilename: $!\n";
   my $error=0;
   while(my $line = <$datafh>){
       chomp $line;    
       my $first_char = substr($line, 0, 1);
       if (length($line) != 78 && $line !~ /^\s*$/ && $first_char != chr(26)) {
           $error=1;   # setze Fehler-Flag
           last;        # ueberspringe Rest der Datei
       }
   }
   # Evtl. Namen der fehlerhaften Datei ausgeben
   if ($error) {
       print "File $datafilename ist fehlerhaft!\n";
   }
}

Was hier natürlich noch fehlt, ist der Test auf die führenden Ziffern. Außerdem könnte man noch testen, ob die Leerzeile bzw. das chr(26) wirklich nur am Dateiende vorkommt. Der folgende Code sollte dies machen:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
use strict;
use warnings;

for my $datafilename (@ARGV) {
   open my $datafh, '<', $datafilename or die "cannot open $datafilename: $!\n";
   my $error=0;
   my $last_line=0;
   while(my $line = <$datafh>){
       chomp $line;

       if ($last_line) {
           # Wenn wir hierher kommen, hatte die letzte Zeile einen Fehler
           $error = 1;
           # Einlesen abbrechen
           last;
       }
       if (length $line != 78 || $line !~ /^\d{4}\D/) {
           # keine 78 Zeichen oder keine 4 Ziffern am Anfang

           if ($line =~ /^\s*$/ || substr($line, 0, 1) == chr(26)) {
               # leer oder chr(26) am Anfang, könnte also die letzte Zeile sein
               $last_line=1;
               # versuchen wir mal, die nächste Zeile zu lesen
               next;
           } else {
               # offensichtlich eine fehlerhafte Zeile
               $error = 1;
               # Einlesen abbrechen
               last;
           }
       }
       # Wenn wir hier hin kommen, ist die eingelesene Zeile korrekt
   }
   # Wenn Fehler, Namen der fehlerhaften Datei ausgeben
   if ($error) {
       print "File $datafilename ist fehlerhaft!\n";
   }
}



@opi: Nur damit den Mitlesern das auch klar ist: open() muss keine drei Argumente haben, es reichen zwei. Aber die Variante mit drei Argumenten ist generell sicherer, weil man den Mode nicht im Dateinamen übergeben kann.


Übrigens, das Zeichen mit dem ASCII-Code 26 hat (hier zumindest) nichts mit "Substitute" zu tun, sondern ist das alte End-of-File-Zeichen unter DOS. Wer heute noch mit  der "MS-DOS-Eingabeaufforderung" arbeitet, der kennt es vielleicht, dass man Strg-Z drücken muss, wenn man das Einlesen von STDIN beenden möchte (unter UNIX: Strg-D). Das Strg-Z sendet ein chr(26) an STDIN (Strg-A sendet das Zeichen mit ASCII-Code 1, Strg-B den ASCII-Code 2, etc.), also ein EOF.

View full thread Dateistruktur überprüfen