Batch: Eine TXT Datei intelligent auslesen und in kleinere Dateien aufteilen.
Hallo geschätztes Forum,
auch wenn die Überschrift es so klingen lässt als ob dieses Problem mehr als ausdiskutiert ist, so habe ich nach langer Recherche (auch in anderen Foren) keine Lösung für mein Problem gefunden. Und als letzten Ausweg hoffe ich mit einer direkten Frage was zu finden.
Ich habe einige txt Dateien die je ungefähr 200MB groß sind. Damit ich sie aber weiterverarbeiten kann muss ich sie aufsplitten bzw. intelligent herauslesen. Nein, nicht ganz so stupide wie es zuerst klingt.
Die Struktur der Ur-Dateien sieht so aus:
HeaderZeile
01 Mueller xxxxxxxxx
02 Mueller xxxxxxxxx
.
.
23 Mueller xxxxxxx
01 Koenig xxxxxxx
.
.
31 Koenig xxxx
01 Frank xxxx
.
.
28 Frank xxxxx
FooterZeile
Jetzt darf ich nicht einfach stupide nach einer bestimmten Zeile abschneiden sondern derart, dass:
- Jedes Teil File nicht (viel) mehr als 50MB hat. (d.h. es sollten im Schnitt aus einem 200MB File ca. 4 Teilfiles a 50MB heraus.)
- Jeweils jedes Teil File die Header und -Footer Zeile besitzt
UND!
- NICHT mitten in einem Klienten getrennt wird. d.h. das egal wo getrennt wird, erst nach den Daten des Klienten (zb Koenig) getrennt wird und nicht mitten im Klienten. Damit sind Klienten Daten nicht in zwei Teilfiles separiert.
Da die Datenzeilen der Klienten unterschiedlich lang sind, könnten man mit einer Schleife solange auslesen bis die Datei ca 50MB groß ist, dann noch so lange Zeilen einlesen bis wieder der String kommt mit "01". Dann diese Zeile nicht mehr einlesen sondern dann den Footer anhängen. Dann muss aber genau bei dieser Zeile weitermachen um das nächste Teil File zu befüllen incl. Header und Footer.
Ich komme da echt auf keine Idee wie ich das technisch hinbekommen könnte. Auch weil ich kaum Erfahrung mit Batch Programmierung habe.
Ursprünglich dachte ich da an ein Batch Skript. Aber ein Powershell Skript oder VBS wären zulässig.
Wenn jemand eine gute Idee oder mehr hätte wäre ich wahrhaftig dankbar.
Viele Grüße
auch wenn die Überschrift es so klingen lässt als ob dieses Problem mehr als ausdiskutiert ist, so habe ich nach langer Recherche (auch in anderen Foren) keine Lösung für mein Problem gefunden. Und als letzten Ausweg hoffe ich mit einer direkten Frage was zu finden.
Ich habe einige txt Dateien die je ungefähr 200MB groß sind. Damit ich sie aber weiterverarbeiten kann muss ich sie aufsplitten bzw. intelligent herauslesen. Nein, nicht ganz so stupide wie es zuerst klingt.
Die Struktur der Ur-Dateien sieht so aus:
HeaderZeile
01 Mueller xxxxxxxxx
02 Mueller xxxxxxxxx
.
.
23 Mueller xxxxxxx
01 Koenig xxxxxxx
.
.
31 Koenig xxxx
01 Frank xxxx
.
.
28 Frank xxxxx
FooterZeile
Jetzt darf ich nicht einfach stupide nach einer bestimmten Zeile abschneiden sondern derart, dass:
- Jedes Teil File nicht (viel) mehr als 50MB hat. (d.h. es sollten im Schnitt aus einem 200MB File ca. 4 Teilfiles a 50MB heraus.)
- Jeweils jedes Teil File die Header und -Footer Zeile besitzt
UND!
- NICHT mitten in einem Klienten getrennt wird. d.h. das egal wo getrennt wird, erst nach den Daten des Klienten (zb Koenig) getrennt wird und nicht mitten im Klienten. Damit sind Klienten Daten nicht in zwei Teilfiles separiert.
Da die Datenzeilen der Klienten unterschiedlich lang sind, könnten man mit einer Schleife solange auslesen bis die Datei ca 50MB groß ist, dann noch so lange Zeilen einlesen bis wieder der String kommt mit "01". Dann diese Zeile nicht mehr einlesen sondern dann den Footer anhängen. Dann muss aber genau bei dieser Zeile weitermachen um das nächste Teil File zu befüllen incl. Header und Footer.
Ich komme da echt auf keine Idee wie ich das technisch hinbekommen könnte. Auch weil ich kaum Erfahrung mit Batch Programmierung habe.
Ursprünglich dachte ich da an ein Batch Skript. Aber ein Powershell Skript oder VBS wären zulässig.
Wenn jemand eine gute Idee oder mehr hätte wäre ich wahrhaftig dankbar.
Viele Grüße
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 220101
Url: https://administrator.de/forum/batch-eine-txt-datei-intelligent-auslesen-und-in-kleinere-dateien-aufteilen-220101.html
Ausgedruckt am: 22.04.2025 um 02:04 Uhr
10 Kommentare
Neuester Kommentar
Zitat von @Mr.Jones:
Ja, VB wäre ebenso möglich.
Denke auch, dass eine Adaption dann einfacher wäre wenn es nötig sein sollte.
Danke.
Ja, VB wäre ebenso möglich.
Denke auch, dass eine Adaption dann einfacher wäre wenn es nötig sein sollte.
Danke.
OK. Sind die Dateien vertraulich, oder kannst Du mir so eine 200MB-Datei zum Testen schicken? Text-Dateien lassen sich ja recht gut packen, da dürften nur zwei bis drei MB übrig bleiben ;)
Hi,
es geht auch mit purem Batch.
Würde ich aber nicht empfehlen, es rechnet bestimmt eine Woche
Aufrufen mit dem Namen der Textdatei, zB
Der Output erfolgt in Parts:
Wegen
Das könnte bB geändert werden.
lg.
es geht auch mit purem Batch.
Würde ich aber nicht empfehlen, es rechnet bestimmt eine Woche
@ECHO OFF &SETLOCAL ENABLEDELAYEDEXPANSION
set /a mb50=52428800
set /a fsize=%~z1
set /a pnum=fsize/mb50
set /a psize=fsize/pnum
echo Info: %~1 %fsize% Bytes, %pnum% Parts a ca. %psize% Bytes.
set /a scnt=psize
set /a pcnt=1
<"%~1" set /p "header="
for /f "delims=" %%a in ('findstr /o "^" "%~1"') do (
set "liner=%%a"
for /f "delims=:" %%b in ("%%~a") do set /a lbyte=%%b
set "line=!liner:*:=!"
if !lbyte! gtr !scnt! (
for /f %%b in ("!line!") do set /a rline=1%%b-100 2>nul
if !rline!==1 (
set /a pcnt+=1
if !pcnt!==%pnum% (set /a scnt=2147483647) else set /a scnt+=psize
>"%~1.part!pcnt!" echo(%header%
)
)
>>"%~1.part!pcnt!" echo(!line!
)
set /a fnum=pnum-1
for /l %%a in (1 1 %fnum%) do >>"%~1.part%%a" echo(%line%
script.bat text.txt
.Der Output erfolgt in Parts:
text.txt.part1
, text.txt.part2
usw.Wegen
delayed expansion
werden im Text evtl. vorhandene Ausrufezeichen nicht korrekt übertragen.Das könnte bB geändert werden.
lg.
Hi,
-
- Fehlten Klammern, liefe das Script nicht. Die Schreibweise '
- 'Header' jeder Partdatei sollte die erste Zeile der Quelldatei sein, das funktioniert bei mir.
lg.
-
2^31-1
ist die Grenze dessen, was mit cmd
berechnet werden kann. Soll hier sicherstellen, dass die letzte Partdatei vollständig ist.- Fehlten Klammern, liefe das Script nicht. Die Schreibweise '
echo(
' ist besser als das früher gebräuchliche 'echo.
'.- 'Header' jeder Partdatei sollte die erste Zeile der Quelldatei sein, das funktioniert bei mir.
lg.
Gut, dann kommt hier der Quellcode für ein VB-Programm. Per eMail hast Du es ja schon bekommen, aber der Sinn eines Forums ist ja, daß auch andere davon profitieren können. Also:
Private Sub Form_Load()
Dim Quelldatei As String 'Dateiname der Datenquelle
Dim Zielgroesse As Long 'Zielgröße der Pakete
Dim Dateinummer As Long 'Nummer der Datei, auf die sich die aktuelle Dateioperation bezieht
Dim ErsteZeile As String 'Inhalt der ersten Zeile
Dim Zeile As String 'Jeweils ausgelesene Zeile
Dim Groesse(50) As Long 'Schon geschriebene Länge der jeweiligen Zieldatei
Dim Flag1 As Long 'Zeiger, der anzeigt, daß bei der aktuellen Ausgabedatei die Zielgröße erreicht ist
Dim Dateien 'Hilfsvariable beim Schlußdurchlauf (Letzte Zeile an alle Ausgabedateien anfügen)
Quelldatei = "d:\Testfile.txt" ' Dateiname der aufzuteilenden Datei
Zielgroesse = 5 * 1048576 '5 * 1048576 Bytes = 5 MB
Open Quelldatei For Input As 1
Line Input #1, ErsteZeile
Dateinummer = 1
Flag1 = 1
Do While Not EOF(1)
Line Input #1, Zeile
If Left(Zeile, 8) = "99999999" Then
' Dies ist die letzte Zeile, sie wird an alle Ausgabedateien angehängt und alle Dateien werden geschlossen
' Anschließend wird die Routine verlassen, ohne dass die anderen Schritte noch bearbeitet werden
For Dateien = 2 To Dateinummer
Print #Dateien, Zeile
Close Dateien
Next
Close 1
Exit Do
End If
If Left(Zeile, 2) = "01" And Flag1 = 1 Then
' Ein neuer Client beginnt UND das Flag, daß bei der Ausgabedatei die Zielgröße überschritten ist, ist gesetzt
' Es wird eine neue Ausgabedatei geöffnet und die erste Zeile wird dort hineingeschrieben
' Danach geht es weiter im normalen Ablauf
Flag1 = 0
Dateinummer = Dateinummer + 1
Open Left(Quelldatei, Len(Quelldatei) - 4) & "_teil" & Str(Dateinummer - 1) & ".txt" For Output As Dateinummer
Print #Dateinummer, ErsteZeile
Groesse(Dateinummer) = Groesse(Dateinummer) + Len(ErsteZeile) 'Hier wird protokolliert, wie groß die aktuelle Ausgabedatei schon ist
End If
' Die aktuelle Zeile aus der Quelldatei wird in die aktuelle Ausgabedatei geschrieben:
Print #Dateinummer, Zeile
'Hier wird protokolliert, wie groß die aktuelle Ausgabedatei schon ist:
Groesse(Dateinummer) = Groesse(Dateinummer) + Len(Zeile)
' Wenn die Größe die Zielgröße überschritten hat, wird ein Flag gesetzt, daß beim nächsten Clienten eine neue Ausgabedatei begonnen wird:
If Groesse(Dateinummer) > Zielgroesse Then Flag1 = 1
Loop
MsgBox "Auftrag abgeschlossen"
End Sub
Und hier noch mal für alle die Anmerkungen aus meiner eMail: Das Programm ist erst mal ganz einfach gestrickt und enthält keine Fehlerabfangroutinen oder so. Das heißt, das Programm ist darauf ausgelegt, daß maximal 49 Teildateien entstehen. Werden es mehr, stürzt das Programm ab. Das Programm enthält auch keinen Dateiauswahldialog, sondern der Dateiname der Quelldatei samt Pfad wird in Zeile 12 fest eingetragen. Natürlich geht das besser, man könnte z.B. ein Verzeichnis angeben und alle darin enthaltenen Dateien automatisch abarbeiten. Aber dazu kenne ich Deine Strukturen zu wenig, so daß ich mich jetzt erst mal auf den Kern, also das Aufsplitten beschränkt habe.