Textdateien verschmelzen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Textdateien verschmelzen

Beitrag von Nino »

Aus gegebenem Anlass poste ich hier mal ein allgemeines „Gerüst“ das zeigt, wie sich Textdateien miteinander verschmelzen lassen.
Nach dem Lesen der Variablen 'line1$' und 'line2$' kann deren Inhalt selbstverständlich geändert werden, bevor er in die Ausgabe-Datei geschrieben wird.

Code: Alles auswählen

; -- erfolgreich getestet mit PB 6.00

EnableExplicit

Procedure.i MergeTextFiles (inFile1$, inFile2$, outFile$)
   ; -- Zwei Textdateien zu einer neuen verschmelzen, indem aus
   ;    beiden Dateien abwechselnd je eine Zeile genommen wird.
   ; in : inFile1$, inFile2$: Namen der beiden Eingabe-Dateien;
   ;                          Format UTF-8 mit oder ohne BOM.
   ;      outFile$          : Name der zu erzeugenden Ausgabe-Datei;
   ;                          Sie wird das Format UTF-8 ohne BOM haben.
   ; out: Funktionswert: 0 bei Fehler, 1 bei Erfolg
   Protected.i ifn1, ifn2, remaining, ofn, fmt
   Protected line1$, line2$
   
   ; -- Alle beteiligten Dateien öffnen und Eingabe-Formate prüfen.
   ifn1 = ReadFile(#PB_Any, inFile1$)
   If ifn1 = 0
      ProcedureReturn 0
   EndIf
   fmt = ReadStringFormat(ifn1)
   If fmt <> #PB_Ascii And fmt <> #PB_UTF8
      CloseFile(ifn1)
      ProcedureReturn 0
   EndIf
   
   ifn2 = ReadFile(#PB_Any, inFile2$)
   If ifn2 = 0
      CloseFile(ifn1)
      ProcedureReturn 0
   EndIf
   fmt = ReadStringFormat(ifn2)
   If fmt <> #PB_Ascii And fmt <> #PB_UTF8
      CloseFile(ifn1)
      CloseFile(ifn2)
      ProcedureReturn 0
   EndIf
   
   ofn = CreateFile(#PB_Any, outFile$)
   If ofn = 0
      CloseFile(ifn1)
      CloseFile(ifn2)
      ProcedureReturn 0
   EndIf
   
   ; -- Schleife, solange beide Eingabe-Dateien noch nicht zu Ende gelesen sind.
   remaining = 0
   Repeat
      If Eof(ifn1)
         remaining = ifn2
         Break
      ElseIf Eof(ifn2)
         remaining = ifn1
         Break
      Else   
         line1$ = ReadString(ifn1)
         line2$ = ReadString(ifn2)
         WriteStringN(ofn, line1$)
         WriteStringN(ofn, line2$)
      EndIf
   ForEver   
   
   ; -- Eine Eingabe-Datei ist zu Ende gelesen.
   ;    Falls in der anderen noch Zeilen übrig sind, auch diese in die Ausgabe-Datei schreiben.
   If remaining = ifn1
      While Eof(ifn1) = #False
         line1$ = ReadString(ifn1)
         WriteStringN(ofn, line1$)
      Wend   
   ElseIf remaining = ifn2
      While Eof(ifn2) = #False
         line2$ = ReadString(ifn2)
         WriteStringN(ofn, line2$)
      Wend   
   EndIf
   
   ; -- Alle beteiligten Dateien schließen und Code für Erfolg zurückgeben.
   CloseFile(ifn1)
   CloseFile(ifn2)
   CloseFile(ofn)
   ProcedureReturn 1
EndProcedure


; -- Demo
Define path$, inFile1$, inFile2$, outFile$

path$ = "C:\Users\Nino\Desktop\"

inFile1$ = path$ + "Liste1.txt"
inFile2$ = path$ + "Liste2.txt"
outFile$ = path$ + "Liste_gesamt.txt"

If MergeTextFiles(inFile1$, inFile2$, outFile$)
   Debug "Erfolg, s. Datei '" + outFile$ + "'"
Else
   Debug "Fehler"
EndIf
Zuletzt geändert von Nino am 26.10.2022 23:41, insgesamt 1-mal geändert.
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Zwei Textdateien verschmelzen

Beitrag von Macros »

Interessante Aufgabe.

Hier wie ich sie gelöst hätte:

Code: Alles auswählen

EnableExplicit

Procedure.i MergeTextFiles (Array infile$(1), outFile$)
  ; -- Beliebig viele Textdateien zeilenweise zu einer neuen verschmelzen.
  ; in : infile$(1)        : Dateinamen der Eingabe-Dateien;
  ;                          Format UTF-16, UTF-8, ASCII mit oder ohne BOM.
  ;      outFile$          : Name der zu erzeugenden Ausgabe-Datei;
  ;                          Sie wird das Format UTF-8 ohne BOM haben.
  ; out: Funktionswert: 0 bei Fehler, 1 bei Erfolg
  Protected num_files= ArraySize(infile$())+1
  Protected Dim file_handle.i(num_files)
  Protected Dim file_format.i(num_files)
  Protected ofn
  Protected a,b, open_files
  
  
  ; -- Alle beteiligten Dateien öffnen und Eingabe-Formate prüfen und speichern.
  
  For a=0 To num_files-1
    file_handle(a) = ReadFile(#PB_Any, infile$(a))
    If file_handle(a) = 0
      For b = 0 To a-1
        CloseFile(file_handle(b))
      Next
      ProcedureReturn 0
    EndIf
    file_format(a) = ReadStringFormat(file_handle(a))
    If file_format(a) <> #PB_Ascii And file_format(a) <> #PB_UTF8 And file_format(a) <> #PB_Unicode
      ; Auch alle vorherigen Dateien müssen aufgeräumt werden
      For b=0 To a 
        CloseFile(file_handle(b))
      Next
      ProcedureReturn 0
    EndIf
  Next
  
  ; Ausgabedatei erstellen
  ofn = CreateFile(#PB_Any, outFile$)
  If ofn = 0
    For a=0 To num_files-1
      CloseFile(file_handle(b))
    Next
    ProcedureReturn 0
  EndIf
  
  ; -- Schleife, solange Eingabe-Dateien noch nicht zu Ende gelesen sind.
  open_files = num_files
  Repeat
    
    For a=0 To num_files-1
      
      If file_handle(a)
        ; Am Ande der Datei schließen wir sie und setzen den Handle auf 0, damit sie später ignoriert wird.
        If Eof(file_handle(a))
          open_files - 1
          CloseFile(file_handle(a))
          file_handle(a) = 0
        Else
          ; Sonst lesen wir eine Zeile im gespeicherten Format und schreiben sie
          WriteStringN( ofn , ReadString(file_handle(a), file_format(a) ) )
        EndIf
      EndIf
      
    Next
    
  Until open_files = 0
  
  ; -- Alle beteiligten Dateien schließen und Code für Erfolg zurückgeben.
  CloseFile(ofn)
  ProcedureReturn 1
EndProcedure


; -- Demo
Define path$, inFile1$, inFile2$, outFile$

path$="X:\"

Dim Infile$(1)
Infile$(0) = path$ + "Liste1.txt"
Infile$(1) = path$ + "Liste2.txt"
outFile$ = path$ + "Liste_gesamt.txt"


If MergeTextFiles(Infile$(), outFile$)
  Debug "Erfolg, s. Datei '" + outFile$ + "'"
Else
  Debug "Fehler"
EndIf
Unterschiede:
  • Man kann nun beliebig viele Dateien zusammenfügen.
  • Der Code kann auch mit UTF-16 umgehen indem er sich das Format merkt
  • Und es ist sogar etwas kürzer :D

Edit:
Noch den Schnipsel in der Antwort ergänzt
Zuletzt geändert von Macros am 26.10.2022 19:56, insgesamt 1-mal geändert.
Bild
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Zwei Textdateien verschmelzen

Beitrag von Nino »

@Macros:
Super, danke! :allright:

Eine Kleinigkeit fehlt in deinem Code allerdings noch.
Aktueller Code:

Code: Alles auswählen

  For a=0 To num_files-1
    file_handle(a) = ReadFile(#PB_Any, infile$(a))
    If file_handle(a) = 0
      ProcedureReturn 0
    EndIf
    [...]
Es fehlt eine Schleife, welche bei einem Fehler beim Öffnen einer Datei die bis dahin geöffneten Dateien wieder schließt (ähnlich wie sie an anderer Stelle deines Codes vorkommt).
D.h. ich würde diese Stelle so schreiben:

Code: Alles auswählen

  For a = 0 To num_files-1
    file_handle(a) = ReadFile(#PB_Any, infile$(a))
    If file_handle(a) = 0
      For b = 0 To a-1
        CloseFile(file_handle(b))
      Next
      ProcedureReturn 0
    EndIf
    [...]
Benutzeravatar
Macros
Beiträge: 1361
Registriert: 23.12.2005 15:00
Wohnort: Olching(bei FFB)
Kontaktdaten:

Re: Zwei Textdateien verschmelzen

Beitrag von Macros »

Da hast du natürlich vollkommen recht :)

Ich habs oben noch ergänzt, damit jemand den vollständigen Code kopieren kann.
Bild
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Textdateien verschmelzen

Beitrag von Nino »

Ich habe das Wort „Zwei“ aus dem Thread-Titel entfernt. :-)
Antworten