Mehrere Dateien (über 400) in mehrere Dateien (dynamisch) zusammenfassen ?

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
lastyle
User
Beiträge: 2
Registriert: Montag 24. August 2020, 22:16

Hallo zusammen,

ich stehe vor dem Problem das ich mehrere Dateien mit numerisch aufsteigenden Dateinamen in wiederum mehrere Dateien , auch mit numerisch aufsteigenen Dateinamen zusammenfügen möchte.

Die quelldateien haben z.b. die Namen :
s 1 m 3940
s 1 m 3945
s 1 m 3950
etc bis
s 1 m 5060

nun möchte ich die Dateien zusammenfügen so das nachher in 200er Schritten die Dateinamen auftauchen was dann wäre : (startend dann bei einer niedrigeren Nummer damit das verarbeitende System damit umgehen kann) , dies und das zugehörige padden am anfang habe ich auch bereits erfolgreich implementiert
s 1 m 3800
s 1 m 4000
s 1 m 4200
etc

für das erste neue paket schreibe ich die zusammenzufügenden Dateinamen in eine Liste und verarbeite diese dann mit :
while firstmsgpack < firstmsgpacknew+newmsgnum: # detect which packages can be added to first new messagepack (actually s 1 m 3940 to s 1 m 3995 resulting in s 1 m 3800)
with open("s "+str(i+1)+" m "+str(firstmsgpack)+".seq", 'rb' ) as subfile:
packnames.append( "s "+str(i+1)+" m "+str(firstmsgpack)+".seq") # fill array with filenames
firstmsgpack+=5
with open("s "+str(i+1)+" n "+str(firstmsgpacknew)+".seq", 'w') as outfile: # join first new message pack
for fname in packnames:
with open(fname) as infile:
outfile.write(infile.read())
Das funktioniert auch alles wunderbar.

Mir fehlt jedoch die Idee wie ich die folgenden Dateien ab "s 1 m 4000 bis s 1 m 5060" in einer schleife erstellen lasse und dann bei 4195 den break mache um die datei zu erstellen, und die schleife dann bei 4200 die liste mit neuen dateinamen füllt um bei 4395 dann wiederrum die nächste datei zu erstellen usw

quasi eine Schleife die vergleicht solange "firstmsgpack" kleiner 5060, adde die 5er pakete und mach bei 4195 den speicherjob und starte das zählen von vorne bis 4395

Hat da jemand eine Idee für mich ?
lastyle
User
Beiträge: 2
Registriert: Montag 24. August 2020, 22:16

Um das mal etwas "einfacher" zu gestalten

Wie wäre das äquivalent zu der folgenden Basic Lösung ?
a=3940
b=5630
x=200
y=5
arr=""


looproutine
for i as integer = y to x step y
arr=arr+"s"+str(a)
a=a+y
next i
if a < b + y then
arr=""
goto looproutine
else
alldone

alldone
exit
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@lastyle: BASIC mit GOTO ist die falsche Richtung. Teile Dein Problem auf kleinere Teilprobleme auf. Und die dann wieder auf kleinere Teilprobleme. Solange bis sich einzelne Teilprobleme jeweils mit einer Funktion mit wenigen Zeilen Code lösen lassen. Immer wenn Du so eine Teillösung hast, testest Du die. Erst mit der nächsten Funktion weitermachen wenn die aktuell geschriebene Funktion tatsächlich das tut was sie soll.

Aus den kleinen Teillösungen lassen sich dann grössere Teillösungen zusammensetzen. Die man wieder testet. Und ehe man sich versieht hat man eine Gesamtlösung.

Dann solltest Du dringend an den Namen in Deinem Programm arbeiten. Man muss beim Programmieren keine Konsonanten kaufen wie beim Glücksrad. UndzwischenraumzwischenWortenerleichtertdaslesenungemein. Also in Namen sind das dann Unterstriche zwischen den einzelnen Worten.

Dann ist Zeichenketten und Werte mit `str()` und ``+`` zusammenstückeln BASIC und nicht Python. In Python gibt es dafür Zeichenkettenformatierung mit der `format()`-Methode und f-Zeichenkettenliterale.

Das mit den niedrigeren Nummern in den Dateinamen sehe ich skeptisch wenn dadurch am irgendwann Dateien überschrieben werden und man überzählige/zusammengefasste Dateien löschen muss. Sicherer ist es das Ergebnis in ein neues, leeres Verzeichnis zu schreiben. Keine Gefahr das man etwas überschreibt, oder alte Dateien beim löschen übersieht, oder aus versehen zu viel löscht.

Wenn Du die Nummern der Dateien im Programm generierst, solltest Du Dir auch Gedanken über Fehler machen die dabei auftreten können. Also beispielsweise fehlende Dateien.

Ein Blick auf das `pathlib`-Modul und/oder `shutil`-Modul würde wahrscheinlich Sinn machen.

Alternativ könntest Du Dir FreeBASIC anschauen und das zur Not auch in BASIC mit GOTO und Sprungmarken schreiben. Wobei ich auch dort das zerlegen in Funktionen und Subroutinen bevorzugen würde. https://freebasic.net/
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

@lastyle:
Wie genau ich in deinem Fall Vorgehen würde, hängt von verschiedenen Dingen ab, die du hier nicht geschrieben hast.
Steht in den Dateien selbst auch nochmal die Position in der Sequenz? Also "s 1 m 4000"? Zum Beispiel als durch zeilengetrennte Datensätze, die als ein Feld eben auch diese Information enthalten?
Wofür steht die Zahl hinter dem "s"? Das ist in deinem Code leider nur als nichtssagendes "i" benannt. Kann sich die Zahl in einer Sequenz ändern? Zum Beispiel, weil das "s" für Stunde steht?

Und noch als Erklärung wegen dem Zusammenstückeln von Zeichenketten mit +: Das macht man nicht, weil es so viel schöner ist:

Code: Alles auswählen

>>> s = 1
>>> m = 3950
>>> print(f"s {s} m {m}.seq")
s 1 m 3950.seq
>>> 
Und zuletzt noch:
Wenn du deinen Code in Code-Tags setzt (erscheinen, wenn man im Vollständiger Editor & Vorschau den </> Button drückt), dann bleiben auch die Einrückungen erhalten.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@lastyle: Ich habe mir das BASIC-Programm noch mal angeschaut und es erst einmal so bearbeitet, das es in QBasic läuft. Dazu muss man `arr` durch ein $-Sigil als Zeichenkette deklarieren, denn sonst gibt es einen TYPE MISMATCH.

Label müssen mit einem Doppelpunkt abgeschlossen werden, damit sie als solche erkannt werden.

Um das `alldone`-Label anzuspringen braucht man explizit eine GOTO-Anweisung.

Das IF/ELSE braucht ein END IF um das Ende des Konstrukts zu markieren.

EXIT ist Bestandteil einer Anweisung um eine Funktion, Unteroutine, oder Schleife zu verlassen, nicht um das Programm zu beenden. Dafür braucht man entweder END oder SYSTEM.

Zwischenstand:

Code: Alles auswählen

a = 3940
b = 5630
x = 200
y = 5
arr$ = ""

looproutine:
  FOR i = y TO x STEP y
    arr$ = arr$ + "s" + STR$(a)
    a = a + y
  NEXT
  IF a < b + y THEN
    arr$ = ""
    GOTO looproutine
  ELSE
    GOTO alldone
  END IF

alldone:
  END
Allerdings ist das END am Ende des Programms nicht nötig, denn der Programmfluss ist da ja sowieso zuende.

Und auch der ELSE-Zweig ist überflüssig, denn wenn im IF nicht zu `looproutine` gesprungen wird, dann geht die Kontrolle ja sowieso zu dem `alldone`. Damit ist auch das `alldone`-Label überflüssig, denn das ist ohne den ELSE-Teil kein Sprungziel mehr.

Code: Alles auswählen

a = 3940
b = 5630
x = 200
y = 5
arr$ = ""

looproutine:
  FOR i = y TO x STEP y
    arr$ = arr$ + "s" + STR$(a)
    a = a + y
  NEXT
  IF a < b + y THEN
    arr$ = ""
    GOTO looproutine
  END IF
Die Zuweisung einer leeren Zeichenkette an `arr$` ist ungünstig platziert. Wenn man das direkt nach `looproutine` macht, dann muss diese Zuweisung nur *einmal* im Programm stehen:

Code: Alles auswählen

a = 3940
b = 5630
x = 200
y = 5

looproutine:
  arr$ = ""
  FOR i = y TO x STEP y
    arr$ = arr$ + "s" + STR$(a)
    a = a + y
  NEXT
  IF a < b + y THEN GOTO looproutine
Nun sollte man das GOTO und das Label noch durch eine ordentliche Schleife ersetzen:

Code: Alles auswählen

a = 3940
b = 5630
x = 200
y = 5

DO
  arr$ = ""
  FOR i = y TO x STEP y
    arr$ = arr$ + "s" + STR$(a)
    a = a + y
  NEXT
LOOP WHILE a < b + y
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@lastyle: Ich habe mir das BASIC-Programm noch mal angeschaut und es erst einmal so bearbeitet, das es in QBasic läuft. Dazu muss man `arr` durch ein $-Sigil als Zeichenkette deklarieren, denn sonst gibt es einen TYPE MISMATCH.

Label müssen mit einem Doppelpunkt abgeschlossen werden, damit sie als solche erkannt werden.

Um das `alldone`-Label anzuspringen braucht man explizit eine GOTO-Anweisung.

Das IF/ELSE braucht ein END IF um das Ende des Konstrukts zu markieren.

EXIT ist Bestandteil einer Anweisung um eine Funktion, Unteroutine, oder Schleife zu verlassen, nicht um das Programm zu beenden. Dafür braucht man entweder END oder SYSTEM.

Zwischenstand:

Code: Alles auswählen

a = 3940
b = 5630
x = 200
y = 5
arr$ = ""

looproutine:
  FOR i = y TO x STEP y
    arr$ = arr$ + "s" + STR$(a)
    a = a + y
  NEXT
  IF a < b + y THEN
    arr$ = ""
    GOTO looproutine
  ELSE
    GOTO alldone
  END IF

alldone:
  END
Allerdings ist das END am Ende des Programms nicht nötig, denn der Programmfluss ist da ja sowieso zuende.

Und auch der ELSE-Zweig ist überflüssig, denn wenn im IF nicht zu `looproutine` gesprungen wird, dann geht die Kontrolle ja sowieso zu dem `alldone`. Damit ist auch das `alldone`-Label überflüssig, denn das ist ohne den ELSE-Teil kein Sprungziel mehr.

Code: Alles auswählen

a = 3940
b = 5630
x = 200
y = 5
arr$ = ""

looproutine:
  FOR i = y TO x STEP y
    arr$ = arr$ + "s" + STR$(a)
    a = a + y
  NEXT
  IF a < b + y THEN
    arr$ = ""
    GOTO looproutine
  END IF
Die Zuweisung einer leeren Zeichenkette an `arr$` ist ungünstig platziert. Wenn man das direkt nach `looproutine` macht, dann muss diese Zuweisung nur *einmal* im Programm stehen:

Code: Alles auswählen

a = 3940
b = 5630
x = 200
y = 5

looproutine:
  arr$ = ""
  FOR i = y TO x STEP y
    arr$ = arr$ + "s" + STR$(a)
    a = a + y
  NEXT
  IF a < b + y THEN GOTO looproutine
Nun sollte man das GOTO und das Label noch durch eine ordentliche Schleife ersetzen:

Code: Alles auswählen

a = 3940
b = 5630
x = 200
y = 5

DO
  arr$ = ""
  FOR i = y TO x STEP y
    arr$ = arr$ + "s" + STR$(a)
    a = a + y
  NEXT
LOOP WHILE a < b + y
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten