Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » Perl/CGI » Vorhandene Datei ändern

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
10.03.2009, 09:24 Uhr
Dirk1980



Hallo zusammen,

ich habe ein Skript geschrieben, welches alle Leerzeilen einer Datei entfernt. Es funktioniert sogar. Dennoch bin ich nicht sehr zufrieden damit.


Perl:

#!/usr/bin/perl
use strict;
use warnings;

use File::Find;

my $dir = "X:/Results";
my $no_files = 0;
my $no_txt_files = 0;
my $no_dirs = 0;
my @file_lines;
my $line;

find(\&edits, $dir);

print "\n\n";
print "Anzahl Verzeichnisse: $no_dirs " . "\n";
print "Anzahl Dateien: $no_files " . "\n";
print "Anzahl txt-Dateien: $no_txt_files " . "\n";

sub edits()
{
    my $file_name = $_;
    if( -f $file_name )
    {
        $no_files += 1;

        if( $file_name =~ m/\.txt$/ )
        {
            $no_txt_files += 1;
            
            # open file in read modus
            open(FILE_HANDLE, "<", $file_name);
            @file_lines = <FILE_HANDLE>;
            print "Anzahl Zeilen: " . @file_lines . "\n";
            close(FILE_HANDLE);
            
            open(FILE_HANDLE, ">", $file_name);
            foreach $line (@file_lines)
            {
                chomp $line;
            
                if( $line !~ m/^\s*$/ )
                {
                    print FILE_HANDLE $line . "\n";
                }
            }            
            close(FILE_HANDLE);
        }
    }
}



Ich lese die ganze Datei ein. Wenn die Datei riesig wäre, so ist es kein guter Ansatz. Am liebsten wäre es mir Zeile für Zeile einzulesen. Das habe ich auch probiert. Doch dann geht alles durcheinander, weil ich in dieselbe Datei lese und schreibe.


Fragen:
1.) Wie würdet ihr es machen alle Leerzeilen einer Datei zu entfernen ohne eine zweite Datei zu benutzen?

2.) Nehmen wir an, dass ich eine riesige txt-Datei habe. In Zeile 34234323 steht "Hallo". Wie könnte ich sehr effizient das "Hallo" in dieser Zeile durch "Hello" ersetzen?

Vielen Dank schon einmal und Gruß
Dirk
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
10.03.2009, 10:50 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


naja, "Hallo" durch "Hello" ersetzen geht gut, da deine Zeilen von der länge her nicht verändert werden. Sobald das aber geschieht, muss die Datei umkopiert werden.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
10.03.2009, 17:04 Uhr
0xdeadbeef
Gott
(Operator)


Ich würde prinzipiell nie auf der selben Datei arbeiten, wenn es sich vermeiden lässt. Es ist stumpf nicht sicher - wenn dein Programm in der Mitte abstürzt (oder abgeschossen wird), behältst du sehr leicht korrupte Dateien übrig.

Versuch, deine Operationen so atomisch wie möglich zu halten, und immer mindestens einen konsistenten Zustand zu behalten. Ich verfahre üblicherweise so:

Lies foo.txt, schreibe nach foo.txt.new; sobald fertig, verschiebe foo.txt nach foo.txt~, dann foo.txt.new nach foo.txt.

Auf die Weise verfährt z.B. auch emacs. Der springende Punkt hier ist, dass zu keinem Zeitpunkt der komplette Datensatz in Gefahr ist. Schmierst du bei der Verarbeitung ab, befindet sich der ursprüngliche Datensatz in foo.txt. Schmierst du beim Verschieben um, hast du jederzeit noch mindestens einen der beiden konsistenten Zustände (vor und nach Verarbeitung), und bei einem ausreichend zeitgemäßen Dateisystem sowieso immer beide, weil die Verschiebeoperation dort atomisch ist.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
11.03.2009, 10:11 Uhr
Dirk1980



Hallo,

vielen Dank für Eure Antworten. Gerade der Tipp von zur Sicherheit der Daten ist sehr wertvoll. In Zukunft werde ich dies bei meinen Skripts beachten.

Hier nun das neue Skript, welches nun sicher sein sollte:

Perl:

#!/usr/bin/perl
use strict;
use warnings;

use File::Find;
use File::Copy;

my $dir = "X:/Results";
my $no_files = 0;
my $no_txt_files = 0;
my $no_dirs = 0;
my @file_lines;
my $line;

find(\&edits, $dir);

print "\n\n";
print "Anzahl Verzeichnisse: $no_dirs " . "\n";
print "Anzahl Dateien: $no_files " . "\n";
print "Anzahl txt-Dateien: $no_txt_files " . "\n";

sub edits()
{
    my $file_name = $_;
    if( -f $file_name )
    {
        $no_files += 1;

        if( $file_name =~ m/\.txt$/ )
        {
            $no_txt_files += 1;
            
            # read input file (e.g. foo.txt)
            open(IN_FILE, "<", $file_name);
            @file_lines = <IN_FILE>;
            close(IN_FILE);
            
            # write to output file (e.g. foo.txt.new)
            open(OUT_FILE, ">", $file_name . ".new");
            foreach $line (@file_lines)
            {
                chomp $line;
            
                # if line is not empty
                if( $line !~ m/^\s*$/ )
                {
                    print OUT_FILE $line . "\n";
                }
            }            
            close(OUT_FILE);
            
            # move input data to backup file (e.g. foo.txt --> foo.txt~)
            move($file_name, $file_name . "~");
            
            # move output data to file which shall be modified (e.g. foo.txt.new --> foo.txt)
            move($file_name . ".new", $file_name)
        }
    }
}



Ich habe gerade auch gesehen, dass die letzte Zeile jeder Datei eine Leerzeile ist. Mir ist klar, warum das so ist. Die letzte Zeile, die ich in die Datei schreibe hat am Ende das "\n". Und dadurch wird eine neue Zeile angelegt.

Wie ist hier die Konvention? Sollte die letzte Zeile einer Textdatei leer sein? Oder ist das völlig egal?

Gruß
Dirk
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
11.03.2009, 11:10 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


naja das kannst du machen wie du willst, meistens jedoch sinnvoll, das die letzte Datenzeile auch wirklich mit einen new-line abgeschlossen ist. Subversion, gcc und viele andere meckern bzw warnen einen z.b wenn eine Datei kein Newline am ende hat.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
11.03.2009, 17:07 Uhr
0xdeadbeef
Gott
(Operator)


Ein Newline am Ende einer Textdatei ist meistens sinnvoll, weil sie sich auf die Art mit generischen Tools meistens besser handhaben lässt. Zum Beispiel

bash:

$ cat bla*.txt > allezusammen.txt


...oder auch in Programmiersprachen - ein fehlendes Zeilenende am Ende einer C-Headerdatei kann beim #include zu wilden Effekten führen.

Es mag Fälle geben, in denen es sich verbietet, aber das sind dann eher Spezialfälle, in denen die Gründe sich selbst erklären. Generell lohnt es sich im Zeitalter von Terabytefestplatten nicht, bei Textdateien ein Byte einsparen zu wollen.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
12.03.2009, 00:33 Uhr
0xdeadbeef
Gott
(Operator)


Kleiner Nachtrag noch zu der Dateigeschichte, dieser Artikel:

www.heise.de/open/Moeglicher-Datenverlust-bei-Ext4--/news/meldung/134346

betrifft genau dieses Problem.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ Perl/CGI ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: