diverse fragen bezüglich file handling

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Gast

Freitag 27. Mai 2005, 09:21

Hallo allerseits,
ich hätte ein paar kurze fragen in Bezug auf dateioperationen, da ich es einfach nicht blicke und nichts geeignetes dazu finden kann...

1) wenn ich ein existierendes file MIT INHALT mit dem Attribut "w" öffne und dann gleich wieder schließe ist der Inhalt weg!?! muss ich also mit "rw" öffnen nur um zu lesen und schreiben?

2) Desweiteren kann ich wenn ich das existierende file mit Inhalt mit "rw" öffne zwar daraus lesen aber dann irgendwie nicht reinschreiben...
also habe mit readlines alle Zeilen rausgelesen und dann auf readlines operiert aber als ich dann readlines wieder in das file reinschreiben wollte kommt Bad File Descriptor...??

2) Ich würde gerne alle Zeilen die mit einem Stern beginnen löschen und alle Zeilen die leer sind also ein "\n" enthalten auch löschen.
habe das so gemacht:
file öffnen mit "rw"
dann:
lines = file.readlines()
while "\n" in lines:
lines.remove("\n")

das funktioniert auch....
aber jetzt wieder zurück ins file schreiben mit
for line in lines:
file.write(line)
geht nicht weil Bad File Descriptor?!?

Was mache ich falsch? Oder gibt es eine elegantere Methode einfach die Zeilen die mit Stern und Leerzeilen zu löschen und damit dass File wieder so zurückzugeben???

3) Zusätzlich würde ich gern alle zeilen die mit einem + anfangen in eine Zeile schreiben...also so:
+abc
+def
+ghi
soll werden:
abc def ghi
wie muss die regex da aussehen? Irgendwie nach + matchen und dann replacen oder so.....jemand eine gute Idee??

Danke für die HIlfe!
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Freitag 27. Mai 2005, 09:50

Was hälst du davon deine Source-Datei erstmal umzubenennen in *.BAK o.ä. Danach diese lesen mit "r" und eine neue Datei mit "w" schreiben... Hätte den vorteil, das du besser sehen kannst ob dein Programm alles richtig macht.

Aus den Zeilen mit dem +-Zeichen würde ich erst eine Liste machen und dann mit " ".join(liste) zu einem String wandeln.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Gast

Freitag 27. Mai 2005, 09:58

ja naja ich brauche die originalfiles dann schon noch....ich könnte halt ein .BAK anlegen und dann die orig files überschreiben aber.....naja.

ich habe das problem das löschen der leerzeilen und der zeilen die mit einem * anfangen in einer schleife zu realisieren....

also ich laufe ja über alle lines in readlines() also über jede zeile aber
ich schaffe es nicht alles in dieser schleife zu löschen...
Gast

Freitag 27. Mai 2005, 10:05

mein problem liegt nämlich darin dass ich auch readlines ja nur mit remove löschen kann und remove nur immer das erste herauslöscht..
also ich könnte ja ne while schleife über remove....
gibt es da nicht effizienteres
?
Gast

Freitag 27. Mai 2005, 10:27

also eigentlich bräuchte ich ja nur irgenwie was womit man alle elemente einer liste löscht...also alle \n z.B.....
Benutzeravatar
knekke
User
Beiträge: 100
Registriert: Freitag 29. Oktober 2004, 17:23
Wohnort: Schweden

Freitag 27. Mai 2005, 12:25

zu 1) und 2):
nimm "a" als attribut, dann müsste es gehen. Ein Backup zu erzeugen ist aber prinzipiell immer eine gute Idee.....
Gast

Freitag 27. Mai 2005, 12:34

mit a funktioniert es leider nicht... ich muss es wirklich so machen dass ich zuerst mit r öffne dann herauslese dann das file schließe dann wieder das file mit w öffne und dann reinschreib und dann wieder schließe...


Das kann doch nicht sein oder?
Aber er brint in der Python Shell sowie wenn ich es einfach laufen lasse immer Bad Filedeskriptor Meldung wenn ich es nicht so mache wie oben beschrieben...

Hat jemand schon eine Idee bezüglich des Löschens der leeren Zeilen und des löschens der mit * beginnenden Zeilen?
Gast

Freitag 27. Mai 2005, 12:44

das problem habe ich gelöst....mit den leeren Zeilen und den mit * anfangenden Zeilen..
jetzt müsste ich noch das mit den Plussen hinbekommen...

also
+ a
+ b + c
+ d

sollte werden:
a b + c d

alos plusse am zeilenanfang weg und alles in eine Zeile!
Und das Problem mit dem r , w und a besteht immer noch!
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Freitag 27. Mai 2005, 12:57

Hoi Gast,

zeigst Du uns mal Deinen Code und vielleicht ein Stück Deine Beispieldatei? Dann kann man nämlich sehen was Du willst und wo es hapert.

Und bezüglich der Regexes: Irgendwie Deine Plusse einbinden ist kein Problem - aber u. U. ein völliger Overkill. Auch hier könnten ein paar Snippets Deines Codes und ein Auszug aus Deiner Datei (soll und ist) helfen zu bestimmen wie man es am besten macht.

Gruß,
Christian
Gast

Freitag 27. Mai 2005, 13:05

hi, ja klar..

also sowas :

abcdefgh
* irgendwas
***********
+ aaaaaa
+ bbbbb + cccccc
+ ddddd

*irgendwas
efghijkl
jmnop


sollte werden:

abcdefgh aaaaaa bbbbb + cccccc ddddd
efghijkl
jmnop

Sprich: Alle leerzeilen weg, alle mit *stern beginnenden Zeilen(Kommentare) und alle mit + anfangenden Zeilen sollten in die vorhergehende Zeile angefügt werden so dass eine zeile entsteht.

Code: Alles auswählen

lines = get_file_content( file, path )
               fl = open( path+'/'+file, 'r' )  
               lines = fl.readlines()
               fl.close()

                # Deleting empty lines
                while "\n" in lines:
                        lines.remove("\n")

                # Deleting comments
                resLines = []
                for line in lines:
                        if line[0] == "*":
                                continue
                        resLines.append(line)

                # Forming single line out of '+' beginning lines 
                 # hier will ich das mit den plussen machen.....???


                fl = open( path+'/'+file, 'w' )        
                for line in resLines:   
                        fl.write(line)
                fl.close()

joe

Freitag 27. Mai 2005, 13:30

Anonymous hat geschrieben:

Code: Alles auswählen

                # Forming single line out of '+' beginning lines 
                 # hier will ich das mit den plussen machen.....???

Code: Alles auswählen

ltmp = []
for l in resLines:
    l = l.rstrip("\n")
    if l.startswith("+"):
        ltmp.append(l[1:])
    else:
        ltmp.append("\n"+l)
resLines = ltmp
ungetestet!
joe
Gast

Freitag 27. Mai 2005, 13:44

ÖHA!!!

Krass...es geht! Vielen Dank!!!!

Wünschte ich könnte auch immer so schnell auf die Lösung kommen. Danke vielmals!
joe

Freitag 27. Mai 2005, 13:51

Anonymous hat geschrieben:Krass...es geht! Vielen Dank!!!!
Büdde!
Aber wenn du das schon "krass" findest dann guck dir erstmal an, wie du die anderen beiden aufgaben hättest löschen können ;-)

Code: Alles auswählen

    # Deleting empty lines
    lines = [l for l in lines if l != "\n"]
    # Deleting comments 
    lines = [l for l in lines if not l.startswith("*")]
joe
BlackJack

Samstag 28. Mai 2005, 20:52

Ein paar Kommentare zum originalen Quelltext:

Pfadnamen sollte man mit `os.path.join()` zusammensetzen: ``open(os.path.join(path, filename), 'r')``.

Das löschen der Leerzeilen ist sehr langsam/aufwendig, weil jedesmal alle Zeilen durchgegangen werden um eine Leerzeile zu finden und dann beim `remove()` wieder alle Zeilen von vorne durchgegangen werden bis die Leerzeile gefunden wird um diese dann zu entfernen. Und das für jede Leerzeile!

Beim löschen der Kommentarzeilen wäre eine Umkehr der Bedingung vielleicht klarer. Dann braucht man kein ``continue``. Also nur die Zeilen an die Ergebnisliste anhängen, die nicht mit einem ``*`` beginnen.

Und man könnte natürlich auch beides zusammenfassen:

Code: Alles auswählen

result = list()
for line in lines:
    if not (line.startswith('*') or line == '\n'):
        result.append(line)

# oder als LC:

result = [line for line in lines
          if not (line.startswith('*') or line == '\n')]
Es gibt auf Dateiobjekten ein Gegenstück zu `readlines()`. Das zurückschreiben braucht keine explizite Schleife:

Code: Alles auswählen

fl = open(open(os.path.join(path, filename), 'w')
fl.writelines(resLines)
fl.close()
Und zum Schluss noch ein Versuch von mir:

Code: Alles auswählen

import StringIO
import sys
from itertools import ifilterfalse

def is_unwanted(line):
    """Tests if line is unwanted.  Unwanted lines constists just of whitespace
    or start with an asterisk (``*``).
    """
    return len(line.strip()) == 0 or line.startswith('*')

def my_reader(lines, continuation_prefix='+', predicate=is_unwanted):
    """Returns iterator that filters unwanted lines and concatenates lines
    starting with the `continuation_prefix`.
    
    If a line starts with the `continuation_prefix` it will be appended
    to the previous line.
    """
    line_buffer = list()
    for line in ifilterfalse(predicate, lines):
        if line.startswith(continuation_prefix):
            line_buffer.append(line[len(continuation_prefix):].rstrip('\n'))
        else:
            if line_buffer:
                yield ''.join(line_buffer) + '\n'
            line_buffer = [line.rstrip('\n')]
    # 
    # Yield last buffered line.
    # 
    if line_buffer:
        yield ''.join(line_buffer) + '\n'

test_data = """abcdefgh
* irgendwas
***********
+ aaaaaa
+ bbbbb + cccccc
+ ddddd

*irgendwas
efghijkl
jmnop"""

infile = StringIO.StringIO(test_data)   # or open(in_filename, 'r')
outfile = sys.stdout                    # or open(out_filename, 'w')

outfile.writelines(my_reader(infile))
infile.close()
# outfile.close()   # Not if ``outfile is sys.stdout``.
Antworten