Seite 1 von 1

diverse fragen bezüglich file handling

Verfasst: Freitag 27. Mai 2005, 09:21
von Gast
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!

Verfasst: Freitag 27. Mai 2005, 09:50
von jens
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.

Verfasst: Freitag 27. Mai 2005, 09:58
von Gast
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...

Verfasst: Freitag 27. Mai 2005, 10:05
von Gast
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
?

Verfasst: Freitag 27. Mai 2005, 10:27
von Gast
also eigentlich bräuchte ich ja nur irgenwie was womit man alle elemente einer liste löscht...also alle \n z.B.....

Verfasst: Freitag 27. Mai 2005, 12:25
von knekke
zu 1) und 2):
nimm "a" als attribut, dann müsste es gehen. Ein Backup zu erzeugen ist aber prinzipiell immer eine gute Idee.....

Verfasst: Freitag 27. Mai 2005, 12:34
von Gast
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?

Verfasst: Freitag 27. Mai 2005, 12:44
von Gast
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!

Verfasst: Freitag 27. Mai 2005, 12:57
von CM
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

Verfasst: Freitag 27. Mai 2005, 13:05
von Gast
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()


Verfasst: Freitag 27. Mai 2005, 13:30
von joe
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

Verfasst: Freitag 27. Mai 2005, 13:44
von Gast
ÖHA!!!

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

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

Verfasst: Freitag 27. Mai 2005, 13:51
von joe
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

Verfasst: Samstag 28. Mai 2005, 20:52
von BlackJack
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``.