blacksun
Goto Top

Textdatei per Batch in mehrere aufteilen

Hallo zusammen,

ich habe folgendes Problem.
Ich habe eine Textdatei, die sehr viele Zeilen enthält (>10000 Zeilen).

Eine vorhandene Batch geht her und liest nacheinander eine Zeile aus, macht damit etwas, und schreibt das Ergebnis in eine Ausgabedatei.
So geht die Batch von Zeile zu Zeile, was natürlich entsprechend lange dauert, bis alle Zeilen durch sind.

Nun habe ich mir überlegt, dass man das ganze Parallel laufen lassen könnte.
Sprich ich teile die Quell-Textdatei in mehrere Teile, verteile diese auf mehrere Ordner, und starte in jedem Ordner die jeweilige Batch-Datei, die die Verarbeitung pro Zeile in der jeweiligen Teil-Quell-Datei übernimmt.

Am Ende, wenn alle Batch-Dateien durchgelaufen sind, füge ich die verschiedenen Ausgabe-Dateien der verschiedenen Ordner zusammen.
Das Zusammenfügen mache ich am einfachsten mit dem for-Befehl. Ich lasse in jedem Ordner jeweils die Ausgabedatei zeilenweise lesen und schreibe das ganze dann in eine große Ausgabedatei.

Mein Problem:
Wie teile ich die große Quelldatei in möglichst gleichmäßige Teile auf. Sprich ich habe 10 Ordner, in die jeweils eine Teil-Quelldatei mit ungefähr gleich viel Zeilen soll.

Wie könnte ich sowas am elegantesten machen? Wichtig wäre, dass halt immer genau 10 Teildateien rauskommen.
Sprich wenn nur 10 Zeilen in der großen Quelldatei stehen, dann sollen halt 10 Dateien mit jeweils einer Zeile davon rauskommen, umgekehrt bei 10000 Zeilen eben 1000 Zeilen pro Datei.

Viele Grüße
Martin

Content-Key: 96618

Url: https://administrator.de/contentid/96618

Printed on: April 16, 2024 at 20:04 o'clock

Mitglied: 60730
60730 Sep 10, 2008 at 17:30:41 (UTC)
Goto Top
Servus,

ein möglicher Ansatz wäre:

rem arbeitskopie
copy meinetextdatei.txt meintextdatei.ini
@echo endeglaende >> meintextdatei.ini
find /n "endeglaende" meintextdatei.ini  
so bekommst du schonmal die komplette Anzahl der Zeilen heraus, ohne vorher "wirklich" die ganze Datei mit einer For Schleife durchzuackern.


...aber wie dann weiter?

Das Zusammenfügen mache ich am einfachsten mit dem for-Befehl.
Ich lasse in jedem Ordner jeweils die Ausgabedatei zeilenweise lesen und schreibe das ganze dann in eine große Ausgabedatei.

Eher weniger, mach lieber ein copy text1.txt + text2.txt komplett_text.txt, dein Ziel ist es doch, "schneller" zu werden.

Gruß
Member: bastla
bastla Sep 10, 2008 at 18:07:37 (UTC)
Goto Top
Hallo blacksun!

Wie schon von TimoBeil richtig festgestellt, muss zum Aufteilen jede Zeile gelesen und geschrieben werden, dazu noch die Abfrage, ob die Grenze für einen Teil bereits erreicht ist - wenn das alles in Batch passiert, wird der ev durch die folgende Parallelverarbeitung zu erzielende Vorteil dadurch vermutlich schon zunichte gemacht.

Als Alternative könnte daher (mal wieder face-wink) VBS herhalten:
Quelle = "D:\Datei.txt"  
Ziel = "D:\Teil"  
Set fso = CreateObject("Scripting.FileSystemObject")  
T = Split(fso.OpenTextFile(Quelle).ReadAll, vbCrLF)
U = UBound(T)
S = Int(U / 10)
For i = 1 To 9
	W = ""  
	For j = (i - 1) * S To i * S - 1
		W = W & T(j) & vbCrLF
	Next
	fso.CreateTextFile(Ziel & i & ".tmp", True).Write W  
Next
W = ""  
For j = 9 * S To U
		W = W & T(j) & vbCrLF
Next
fso.CreateTextFile(Ziel & "10.txt", True).Write W  
Für 66000 Zeilen zu je etwa 65 Zeichen läuft das Script bei mir etwa 40 Sekunden ...

Grüße
bastla
Member: Biber
Biber Sep 10, 2008 at 18:52:26 (UTC)
Goto Top
Hmmja, bastla,

das ist natürlich eine Lösung für die Aufgabenstellung (und sogar eine kurze und knackige Lösung!), aber....

Hey, lass uns mal zwei Schritte zurücktreten und dann noch mal draufgucken...

  • Jetzt nudeln wir eine Zig-Zehntausende-Zeilen-Datei in sportlichen 40 sec durch und portionieren die in 10 handlichere Häppchen,....
  • damit danach 10 eher drömelige Bätche es zeitlich auf die Reihe bekommen, vor dem Morgengrauen eines dieser Häppchen abzufrühstücken..
  • und sich dann wie die 7 (+3) Zwerge darum balgen, die Ergebnisse wieder in eine Final-Outputdatei zu schreiben....

Ööööhmmm.....

Also nee....

Jetzt würde ich bewerten und abwägen...
  • wenn das Weiterlaufen der bisherigen Lösung das Ziel ist: Dann soll doch der heutige Batch morgens um 02h per Taskplaner gestartet werden und meinetwegen 2 Stunden rumrödeln
  • wenn Performance-Tuning das Ziel ist, dass lass uns die ganze Aufgabe per VBS (oder besserem) abfackeln. Besser im Sinne von: Weniger Interpreter, mehr Kompilertes.

So wie jetzt möchte ich es als "Lösung" eigentlich nicht im Forum stehen haben.

Grüße
Biber
Member: bastla
bastla Sep 10, 2008 at 19:23:44 (UTC)
Goto Top
@Biber
Dann gilt also für obiges Script: "Habe Lösung - suche Problem." face-wink

Allerdings muss ich Dir (kostet mich allerdings keine Überwindung face-smile) natürlich Recht geben ...

Grüße
bastla
Member: blacksun
blacksun Sep 11, 2008 at 20:59:40 (UTC)
Goto Top
Hallo zusammen,

also das vbs-Skript von bastla funktioniert ganz hervorragend.
Feine Sache.

Vielen Dank.

Viele Grüße
Martin
Member: blacksun
blacksun Sep 11, 2008 at 21:01:16 (UTC)
Goto Top
Hallo bastla,

also das vbs-Skript funktioniert ganz hervorragend.
Feine Sache.

Vielen Dank.

Viele Grüße
Martin
Member: Netkid
Netkid Jan 16, 2019 updated at 17:15:48 (UTC)
Goto Top
Hallo bastla,

das vbs-Prg ist echt super.
Die Orginaldatei wird in gleich große Teile gesplittet.
Wie ändert man das vbs, wenn man fixe Mengen z. B. 20.000 Datensätze pro Teildatei
splitten will und der Rest kommt in die letzte Teildatei?

Gruß, netkid

p.s. Habe doch noch 'ne Lösung gefunden: VBS splitting-large-files-using

Code:
''This simple VBScript spilts large text files into multiple files  
 
Dim  Counter
Const InputFile = "C:\input.txt"  
Const OutputFile = "C:\output"  
Const RecordSize = 200000
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Set objFSO = CreateObject("Scripting.FileSystemObject")  
Set objTextFile = objFSO.OpenTextFile (InputFile, ForReading)
Counter = 0
FileCounter = 0
Set objOutTextFile = Nothing
 
Do Until objTextFile.AtEndOfStream
    if Counter = 0 Or Counter = RecordSize Then
        Counter = 0
        FileCounter = FileCounter + 1
        if Not objOutTextFile is Nothing then objOutTextFile.Close
        Set objOutTextFile = objFSO.OpenTextFile( OutputFile & "_" & FileCounter & ".csv", ForWriting, True)  
    end if
    strNextLine = objTextFile.Readline
    objOutTextFile.WriteLine(strNextLine)
    Counter = Counter + 1
Loop
objTextFile.Close
objOutTextFile.Close
Msgbox "Split process complete"