Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit
GELÖST

Textdatei mit 300.000 Zeilen splitten

Frage Entwicklung VB for Applications

Mitglied: 26705

26705 (Level 1)

13.02.2007, aktualisiert 14.02.2007, 15239 Aufrufe, 12 Kommentare

Moin,

kennt jemand eine Möglichkeit eine Textdatei mit über 300000 Zeilen in nen Haufen kleinere Textdateien mit 2500 Zeilen aufzuteilen?
Hab mich schon an ner Batch probiert aus nem Thread hier probiert (http://www.administrator.de/frage/logfile-letzten-zeilen-in-txt-file-mi ...).
Das funktioniert auch wunderbar, aber nur bis ca. 4000 Zeilen, dann bricht die Batch ab.
Hat jemand noch irgendeine Idee?
Habe hier zur Zeit leider nur Win XP zur Verfügung...
Mitglied: bastla
13.02.2007 um 11:55 Uhr
Hallo SeppelCeh!

Bei der Lösung per Batch gibt es öfters Probleme mit Sonderzeichen wie "&" oder ">", etc, daher eine VB-Script-Variante:
01.
'SplitTextFile.vbs 
02.
sInFile = WScript.Arguments(0) 
03.
If WScript.Arguments.Count < 2 Then 
04.
    lMaxLine = 2500 
05.
Else 
06.
    lMaxLine = CLng(WScript.Arguments(1)) 
07.
End If 
08.
 
09.
Set fso = Wscript.CreateObject("Scripting.FileSystemObject") 
10.
sPath = fso.GetFile(sInFile).Path 
11.
sPath = Left(sPath, InstrRev(sPath, "\") - 1) 
12.
sOutName =  sPath & "\Part_" 
13.
If InstrRev(sInFile, ".") Then 
14.
    sOutType = Mid(sInFile, InstrRev(sInFile, ".")) 
15.
End If 
16.
 
17.
lLineNr=0 
18.
iFileNr=1001 
19.
 
20.
Set oOut = fso.OpenTextFile(sOutName & Mid(CStr(iFileNr),2) & sOutType, 2, True) 
21.
Set oIn = fso.OpenTextFile(sInFile, 1) 
22.
Do While Not oIn.AtEndOfStream 
23.
	oOut.WriteLine oIn.ReadLine 
24.
	lLineNr = lLineNr + 1 
25.
	If lLineNr >= lMaxLine Then 
26.
		lLineNr = 0 
27.
		oOut.Close 
28.
		iFileNr = iFileNr + 1 
29.
		Set oOut = fso.OpenTextFile(sOutName & Mid(CStr(iFileNr),2) & sOutType, 2, True) 
30.
	End If 
31.
Loop 
32.
oIn.Close 
33.
oOut.Close 
34.
WScript.Echo "Done."
Aufruf mit
01.
SplitTextFile.vbs Textdatei ZeilenJeDatei
Alternativ kannst Du auch einfach die Textdatei auf das Script ziehen, dann werden Teildateien mit je 2500 Zeilen erzeugt (siehe "lMaxLine = 2500").

Die Teildateien werden jeweils im Ordner der ursprünglichen Textdatei mit dem gleichen Dateityp abgelegt. Die restliche Namensgebung findet in der Zeile "sOutName = sPath & "\Part_"" statt - "Part_" kannst Du auf Wunsch ersatzlos streichen, der "\" wird benötigt.

In der aktuellen Fassung ist die Anzahl der Teildateien auf 999 beschränkt, durch Änderung der Zeile "iFileNr=1001" auf einen Wert 10001 erhältst Du 4-stellige Dateinamen, also bis zu 9999 Dateien.

Grüße
bastla
Bitte warten ..
Mitglied: 26705
13.02.2007 um 18:37 Uhr
Wunderbar, werde ich morgen früh gleich mal testen.
Wird wohl doch dringend Zeit mich mit VB-Script zu beschäftigen...
Bitte warten ..
Mitglied: 26705
14.02.2007 um 09:41 Uhr
Läuft wunderbar, vielen Dank!!!

Gruß,
Seppel
Bitte warten ..
Mitglied: Celimos
11.01.2012 um 14:49 Uhr
Hallo zusammen!

Beruflich bedingt kenne ich dieses Forum schon längere Zeit und bin ausgesprochen dankbar dafür, da es mir bereits des Öfteren zu einem Problem entweder einen guten Ansatz oder sogar die Lösung geliefert hat. Da ich diesmal jedoch keine Antwort auf meine Frage gefunden habe, habe ich mich nun registriert und hoffe, dass mir eventuell jemand weiterhelfen kann...

Hier nun mein Problem: Über die Exportfunktion in DATEV Kanzlei-Rechnungswesen habe ich zunächst eine CSV-Datei mit Debitorenstammdaten eines Mandanten erstellt. Leider kann ich diese nicht weiterverarbeiten, da das Programm für die Folgebearbeitung eine Größenbeschränkung von 2 MB hat. Meine Export-Datei hat jedoch eine Dateigröße von 20 MB.
Eine Anfrage bei der DATEV-Hotline brachte mich nicht wirklich weiter, da man mir lediglich vorschlug, die Datei einfach händisch zu splitten. Da die Stammdaten jedoch einmal pro Woche über diesen Weg aktualisiert werden müssen, wäre das nicht wirklich praktikabel...
So gesehen hilft mir die von Bastla programmierte Lösung in gewisser Weise weiter, allerdings kommen bei der Verarbeitung durch das obige VB-Script am Ende auch wieder gesplittete CSV-Dateien mit der Endung .csv raus. Zur weiteren Verarbeitung brauche ich jedoch CSV-Dateien mit der Endung .txt. Darüber hinaus habe ich in der Ursprungsdatei am Anfang auch eine feste Anzahl an Zeilen, die als Header dienen und die zur korrekten Verarbeitung in den gesplitteten Dateien jeweils am Anfang vorhanden sein müssten.
Leider gehen meine VBS-Programmierkenntnisse so ziemlich gen Null, so dass ich nun vor einem für mich "unlösbaren" Problem stehe. Daher hoffe ich nun, dass sich jemand meines Problems annimmt und mir damit sehr weiterhelfen würde...

Vielen Dank im Voraus!


Grüße
Celimos
Bitte warten ..
Mitglied: bastla
11.01.2012 um 18:01 Uhr
Hallo Celimos und willkommen als Mitglied!

Eine an Deine Wünsche angepasste (und etwas aktualisierte sow wie oberflächlich getestete) Fassung des Scripts könnte etwa so aussehen:
01.
'SplitTextFile.vbs 
02.
sInFile = WScript.Arguments(0) 
03.
lDataLines = CLng(WScript.Arguments(1)) 
04.
lHeaderLines = CLng(WScript.Arguments(2)) 
05.
sOutFolder = WScript.Arguments(3) 'kann natürlich auch hier fix eingetragen werden, zB: sOutFolder = "Parts" 
06.
sOutFileName = "Part_" 
07.
sOutType = ".txt" 
08.
 
09.
Set fso = CreateObject("Scripting.FileSystemObject") 
10.
sOutPath = fso.GetParentFolderName(fso.GetFile(sInFile).Path) & "\" & sOutFolder 
11.
If Not fso.FolderExists(sOutPath) Then fso.CreateFolder(sOutPath) 'Zielordner bei Bedarf erzeugen 
12.
sOutName = sOutPath & "\" & sOutFileName 'Zielpfad inkl konstantem Namensanteil erstellen 
13.
 
14.
aText = Split(fso.OpenTextFile(sInFile).ReadAll, vbCrLf) 'gesamten Inhalt in Array einlesen 
15.
lLines = (UBound(aText))'höchste Zeilennummer 
16.
iFiles = Int((lLines + 1) / lDataLines + .99999) 'Anzahl Zieldateien 
17.
iDigits = Int(Log(iFiles) / Log(10)) + 1 'Stellenanzahl für Dateinummer 
18.
lLineNr = lHeaderLines '1. Datenzeile (nullbasiert) der Quelldatei 
19.
lFileNr = 1000001 
20.
 
21.
For i = 1 To iFiles 'Schleife für Zieldateien 
22.
    Set oOut = fso.CreateTextFile(sOutName & Right(CStr(lFileNr), iDigits) & sOutType) 'Zieldatei mit lfd Nummer erstellen 
23.
    'Ausgabe Kopfzeilen 
24.
	For j = 1 To lHeaderLines 
25.
        oOut.WriteLine (aText(j - 1)) 
26.
    Next 
27.
    'Ausgabe Zeilen in gewünschter Anzahl 
28.
    For j = 1 To lDataLines 
29.
        If lLineNr > lLines Then Exit For 'letzte Datei enthält uU weniger als lDataLines Zeilen 
30.
        oOut.WriteLine (aText(lLineNr)) 'Zeile schreiben 
31.
        lLineNr = lLineNr + 1 'Quelldatei-Zeilennummer erhöhen 
32.
    Next 
33.
    oOut.Close 'Zieldatei schließen 
34.
    lFileNr = lFileNr + 1 'ldf Nummer für Zieldatei erhöhen 
35.
Next 
36.
WScript.Echo "Done."
Der Aufruf erfolgt mit
SplitTextFile.vbs CSV-Datei Datenzeilenanzahl Kopfzeilenanzahl
Alternativ können auch in den Zeilen 2 bis 4 anstelle von "WScriptArguments(x)" die gewünschten Werte in das Script eingetragen werden - für die Quelldatei würde das so aussehen:
sInFile = "D:\Pfad zur Datei\Datei.csv"
Die Zieldateien werden im Ordner der Quelldatei (siehe Zeile 9 - dort könnte auch ersatzweise ein anderer Pfad festgelegt werden) mit den Namen "Part_###.txt" erstellt (siehe dazu Zeilen 5 und 6), wobei die Stellenanzahl der laufenden Nummer an die Anzahl der Dateien angepasst wird: Entstehen etwa 79 Dateien, lauten deren Namen "Part_01.txt" bis "Part_79.txt", werden es 1235 Dateien, werden diese "Part_0001.txt" bis "Part_1235.txt" benannt.

Jede Zieldatei enthält die angegebene Anzahl von Kopfzeilen + die angegebene Anzahl von Datenzeilen.

Grüße
bastla

[Edit] Korrektur der Berechnung (s.u.) in Zeile 14 (jetzt 16) und Umstellung auf Angabe eines Zielordners als 4. Aufrufparameter [/Edit]
Bitte warten ..
Mitglied: Celimos
12.01.2012 um 15:42 Uhr
Hallo Bastla!

zunächst einmal ganz herzlichen Dank, dass Du mir so schnell eine Lösung "gezaubert" hast! Damit hast Du mir wirklich enorm viel Zeit und Nerven erspart.

Leider wollte das Script jedoch auf Anhieb nicht ganz funktionieren, aber durch Deine Kommentare und Erläuterungen glaube ich auch ohne große VB-Scriptkenntnisse dahintergekommen zu sein, wo sich der "Fehlerteufel" eingeschichen hat. Wenn ich das richtig sehe, müsste das Problem in Zeile 14 bei der Zahl hinter der Variable "lDataLines" liegen, denn damit rundet er ja den Integer-Wert auf die nächst höhere ganze Zahl auf - richtig? Somit müsste die Zeile dann sicher wie folgt lauten:

iFiles = Int((lLines + 1) / lDataLines + 1) 'Anzahl Zieldateien
Geäußert hat sich das Problem dadurch, dass bei der Verarbeitung nur Dateien erzeugt wurden, die die maximal definierte Zeichenanzahl enthielten. Da jedoch die Aufsplittung der Gesamtzeilenanzahl nur im Idealfall genau aufgeht und bei einer Gegenprüfung mit der Ursprungsdatei zudem ein paar Datensätze gefehlt haben, konnte ich den Fehler hierauf eingrenzen.

Nach der Korrektur arbeitet das Script jetzt an sich einwandfrei, allerdings hätte ich noch eine "kleine" Bitte: Sofern es für Dich nicht zu viel Aufwand bedeutet und Du das ganze Script nicht noch mal komplett umschreiben musst, würde ich gerne die gesplitteten Dateien zusätzlich in einen Ordner packen, da es sonst bei der Verwendung auf dem Desktop und einer größeren Anzahl an gesplitteten Dateien schnell unübersichtlich wird. Besondes schön wäre es natürlich, wenn diese Funktion wieder so "flexibel" aufgebaut wäre, wie das restliche Script, so dass es möglich ist, oben in der Datei den Ordnernnamen zu definieren und er mir dann an der Stelle, an der sich das Script befindet, einfach die Dateien in den genannten Ordner packt.
Auch hieran habe ich mich heute bereits längere Zeit erfolglos versucht und wäre ausgesprochen dankbar, wenn Du mir nochmals unter die Arme greifen könntest.


Grüße
Celimos
Bitte warten ..
Mitglied: bastla
12.01.2012 um 16:21 Uhr
Hallo Celimos!

Mit dem Fehler in Zeile 14 (das Problem war nicht das Aufrunden auf die nächste ganze Zahl, sondern das kaufmännische Runden nach der 4/5-Regel, wodurch dann eben öfter nicht aufgerundet wird) hast Du recht, die Korrektur ist ganz knapp an der Optimallösung vorbei - es sollte nämlich nur .99999 addiert werden, damit nicht für den Fall, dass es genau ein Vielfaches der gewünschten Zeilenanzahl gibt, eine Datei zuviel (würde dann nur die Kopfzeilen enthalten) erzeugt wird ...

Ich korrigiere das oben noch und baue auch die Verwendung eines (als 4. Parameter beim Scriptaufruf) vorgegebenen Zielordners ein (den Hinweis auf die Zeile 9 - ist jetzt Zeile 10 - hätte ich gestern vielleicht noch etwas deutlicher formulieren können); beide Änderungen ungetestet ...

Grüße
bastla
Bitte warten ..
Mitglied: Celimos
18.01.2012 um 14:32 Uhr
Hallo Bastla!

entschuldige bitte, dass ich mich erst jetzt wieder melde, aber leider hatte ich die letzten Tage beruflich ziemlich viel um die Ohren...
Nach den letzten Anpassungen läuft Dein Script nun absolut tadellos und erleichtert uns die Arbeit wirklich ungemein! Hierfür nochmals ein herzliches Dankeschön!

Da ich ja in Zukunft nicht immer ankommen und darauf hoffen will, dass mir jemand von Grund auf ein Script programmiert, würde ich mich sehr freuen, wenn Du mir zum Abschluss eventuell noch einen Tipp geben kannst, welche Lektüre ich mir für den Einstieg in die VB-Scriptprogrammierung zulegen könnte. Sofern Du mir dahingehend etwas empfehlen kannst, wäre ich Dir besonders dankbar, wenn diese relativ praxisnah gehalten ist.


Grüße
Celimos
Bitte warten ..
Mitglied: csvmaxi
15.01.2013, aktualisiert um 22:55 Uhr
Hallo Bastla,

nach langen suchen im Netz bin ich auf diese Seite und diesen Artikel gestoßen. Ich habe mich bisher noch gar nicht mit VBA beschäftigt, merke aber, dass es einem viel arbeit abnehmen kann.

Ich habe das Script probier und die anfangswerte in die scriptdatei eingefügt. habe meine 60mb große csv auf das script gezogen. Das script macht alles, aber es fehlen die Datenzeiten. Es ist nur die headline vorhanden. kannst Du dir das ggf. erklären.

Besten Dank im Voraus.

Grüße
Thorsten
Bitte warten ..
Mitglied: bastla
15.01.2013 um 22:56 Uhr
Hallo csvmaxi und willkommen im Forum!
Ich habe das Script probier und die anfangswerte in die scriptdatei eingefügt.
Wie sehen die ersten 7 Zeilen des Scripts bei Dir aus?

Und was genau meinst Du mit
Das script macht alles, aber es fehlen die Datenzeiten. Es ist nur die headline vorhanden.

Grüße
bastla

P.S.: Die Sprache ist übrigens VBS, nicht VBA ...
Bitte warten ..
Mitglied: csvmaxi
16.01.2013 um 01:06 Uhr
Hallo Bastla,

1.anbei die Zeilen:

'SplitTextFile.vbs
sInFile = "D:\1.csv"
lDataLines = "3000"
lHeaderLines = "1"
sOutFolder = "Parts"
sOutFileName = "Part_"
sOutType = ".csv"

Set fso = CreateObject("Scripting.FileSystemObject")

2. In den erstellten Dateien ist nur die Kopfzeilevorhanden, jedoch keine Datensätze.

Thats it is.

Scheinst ja nun im Bett zu liegen. Bin Nachtmensch..

Grüße
Thorsten
Bitte warten ..
Mitglied: bastla
16.01.2013 um 08:02 Uhr
Hallo csvmaxi!

Zahlenwerte sind in Basic (also auch VBS) ohne Anführungszeichen zu schreiben - daher:
01.
'SplitTextFile.vbs 
02.
sInFile = "D:\1.csv" 
03.
lDataLines = 3000 
04.
lHeaderLines = 1 
05.
sOutFolder = "Parts" 
06.
sOutFileName = "Part_" 
07.
sOutType = ".csv" 
08.
 
09.
Set fso = CreateObject("Scripting.FileSystemObject")
Grüße
bastla
Bitte warten ..
Neuester Wissensbeitrag
Internet

Unbemerkt - Telekom Netzumschaltung! - BNG - Broadband Network Gateway

(3)

Erfahrungsbericht von ashnod zum Thema Internet ...

Heiß diskutierte Inhalte
Switche und Hubs
Trunk für 2xCisco Switch. Wo liegt der Fehler? (17)

Frage von JayyyH zum Thema Switche und Hubs ...

Windows Server
Outlook Verbindungsversuch mit Exchange (15)

Frage von xbast1x zum Thema Windows Server ...

Microsoft Office
Keine Updates für Office 2016 (11)

Frage von Motte990 zum Thema Microsoft Office ...