3000 zufällige Zeilen aus TXT mit 22 Mio Zeilen auslesen
Hallo,
ich bin ein Quereinsteiger und arbeite egentlich mit Geo-informationssystemen. Daher habe ich leider keine Erfahrung mit Skripten (außer einfachem Batch-Kopieren von Dateien). Nun habe ich folgendes Problem, bei dem ich hoffe dass mir ein Batch-Skript helfen kann...
Es geht um Folgendes:
Ich habe eine Textdatei in der 22 Mio Koordinatenpunkte gespeichert sind, d.h. in jeder Zeile der TXT sind durch Tabs getrennte x,y und z Werte eines Koordinatensystems gespeichert. Sie ist ca. 700MB schwer. Dabei ist jede Zeile der Textdatei exakt gleichviele Zeichen lang und auch die Anzahl der Zeilen kenne ich. Nun will ich aus diesen vielen Punkten 3000 zufällig herausnehmen, d.h. aus der Textdatei 3000 Zeilen nach dem Zufallsprinzip "ausschneiden" und in eine neue Textdatei schreiben, sodass ich am Ende zwei Dateien erhalte:
a) eine Datei mit den 3000 Zufallspunkten (d.h. Zeilen) und
b) eine Datei mit den verbleibenden 21997000 Mio Zeilen.
Diese Aktion muss ich nur für diese eine Datei durchführen.
Meine Fragen sind nun:
1. Ist das Vorhaben mit einem Batch-Skript grundsätzlich (auf einem normalen Büro-PC) möglich, so dass es sich für mich lohnt mich damit näher zu beschäftigen?
2. Falls das der Fall ist, hat jemand Tipps für die Erstellung eines solchen Skripts?
Es wäre super wenn ihr einem Laien wie mir da weiterhelfen könntet...
Dank und Gruß,
ningiser
ich bin ein Quereinsteiger und arbeite egentlich mit Geo-informationssystemen. Daher habe ich leider keine Erfahrung mit Skripten (außer einfachem Batch-Kopieren von Dateien). Nun habe ich folgendes Problem, bei dem ich hoffe dass mir ein Batch-Skript helfen kann...
Es geht um Folgendes:
Ich habe eine Textdatei in der 22 Mio Koordinatenpunkte gespeichert sind, d.h. in jeder Zeile der TXT sind durch Tabs getrennte x,y und z Werte eines Koordinatensystems gespeichert. Sie ist ca. 700MB schwer. Dabei ist jede Zeile der Textdatei exakt gleichviele Zeichen lang und auch die Anzahl der Zeilen kenne ich. Nun will ich aus diesen vielen Punkten 3000 zufällig herausnehmen, d.h. aus der Textdatei 3000 Zeilen nach dem Zufallsprinzip "ausschneiden" und in eine neue Textdatei schreiben, sodass ich am Ende zwei Dateien erhalte:
a) eine Datei mit den 3000 Zufallspunkten (d.h. Zeilen) und
b) eine Datei mit den verbleibenden 21997000 Mio Zeilen.
Diese Aktion muss ich nur für diese eine Datei durchführen.
Meine Fragen sind nun:
1. Ist das Vorhaben mit einem Batch-Skript grundsätzlich (auf einem normalen Büro-PC) möglich, so dass es sich für mich lohnt mich damit näher zu beschäftigen?
2. Falls das der Fall ist, hat jemand Tipps für die Erstellung eines solchen Skripts?
Es wäre super wenn ihr einem Laien wie mir da weiterhelfen könntet...
Dank und Gruß,
ningiser
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 111702
Url: https://administrator.de/forum/3000-zufaellige-zeilen-aus-txt-mit-22-mio-zeilen-auslesen-111702.html
Ausgedruckt am: 20.05.2025 um 04:05 Uhr
13 Kommentare
Neuester Kommentar
Hallo,
ich habe mir gerade den Kopf darüber zerbrochen und überlegt, ob es mit Batch bzw. normalen VB Script möglich ist.
Nach einigem Lesen bin ich aber sicher, dass Du um die VBMath.Randomize() Funktion von .Net (als Beispiel) nicht drumherum kommen wirst, da Du nur hier große Zufallszahlen in dem Bereich > INT erstellen kannst.
Ich habe zwar versucht, die einzelnen Stellen der "22.000.000" seperat per Zufall zu bestimmen, aber die Verteilung ist einfach nicht zufällig... egal wie oft man Randomize mit Rnd zusammen benutzt.
Nichts desto trotz wird es Dich vielleicht freuen jetzt einen Weg zu wissen, wie man es nicht macht
Du müsstest Du "mal eben" schnell eine Konsolenanwendung in .NET erstellen, die Dir aus den 22000000 insgesamt 3000 Zufallszahlen pickt. Diese Schreibst Du entweder in ein Array (um zu kontrollieren, ob sie wirklich eindeutig sind).
Danach liest Du genau diese Zeilen aus der 22000000 Datei aus und löscht die besagten Zeilen , nachdem Du alle 3000 Zeilen extrahiert hast.
Wünsch noch viel Erfolg
Gruß
Markus
ich habe mir gerade den Kopf darüber zerbrochen und überlegt, ob es mit Batch bzw. normalen VB Script möglich ist.
Nach einigem Lesen bin ich aber sicher, dass Du um die VBMath.Randomize() Funktion von .Net (als Beispiel) nicht drumherum kommen wirst, da Du nur hier große Zufallszahlen in dem Bereich > INT erstellen kannst.
Ich habe zwar versucht, die einzelnen Stellen der "22.000.000" seperat per Zufall zu bestimmen, aber die Verteilung ist einfach nicht zufällig... egal wie oft man Randomize mit Rnd zusammen benutzt.
Nichts desto trotz wird es Dich vielleicht freuen jetzt einen Weg zu wissen, wie man es nicht macht
Du müsstest Du "mal eben" schnell eine Konsolenanwendung in .NET erstellen, die Dir aus den 22000000 insgesamt 3000 Zufallszahlen pickt. Diese Schreibst Du entweder in ein Array (um zu kontrollieren, ob sie wirklich eindeutig sind).
Danach liest Du genau diese Zeilen aus der 22000000 Datei aus und löscht die besagten Zeilen , nachdem Du alle 3000 Zeilen extrahiert hast.
Wünsch noch viel Erfolg
Gruß
Markus
Moin ningiser,
willkommen im Forum.
Wenn das eine einmalige Aktion und Dein Rechner auch die ganze Mittagspause (oder die halbe Nacht) damit verbringen kann, dann geht es auch mit normalem Batchkrams oder ein bis zwei Zeilen am Cmd-Prompt.
Für den ersten Teil der Aufgabe (3000 Zufallszahlen aus roundabout 22 Mio rausfieseln könnte ich Dir eine Skizze anbieten
... hier mal beispielhaft für die ersten dreißig statt dreitausend Zeilen.
[Edit] Erst zu spät gesehen... der "sort" sortiert hier natürlich "literal" und nicht aufsteigend nach Zahlenwerten.
also bitte den "Sort" einfach wegdenken. Ist nicht wesentlich. [/Edit]
Diese Zeilen(nummern) wiederum könnten
Egal... ist alles Schritt 2.
Zu prüfen wäre jetzt von Dir, ob Dir die Streuung der 3000 "Zufalls"-zahlen mit der oben stehenden Mimik ausreicht oder ob eine "bessere" Random()-Funktion eines anderen Tools (VBS / java / #Net / whatever) benötigt wird.
Grüße
Biber
willkommen im Forum.
Wenn das eine einmalige Aktion und Dein Rechner auch die ganze Mittagspause (oder die halbe Nacht) damit verbringen kann, dann geht es auch mit normalem Batchkrams oder ein bis zwei Zeilen am Cmd-Prompt.
Für den ersten Teil der Aufgabe (3000 Zufallszahlen aus roundabout 22 Mio rausfieseln könnte ich Dir eine Skizze anbieten
>(for /L %i in ( 1,1,30) do @set /a x="!random!*!random!">nul & @set /a "y=!x! % 21997000">nul & @echo !y!)|sort
10137224
10153303
10878128
12684210
14344419
15210636
16417280
16557600
17083854
17257936
1857192
2074661
21110862
21343388
21828460
21924535
2686070
282968
2911667
2959750
548502
5697962
6137867
6515124
6667600
7245863
8041045
8313475
8644748
9300321
[Edit] Erst zu spät gesehen... der "sort" sortiert hier natürlich "literal" und nicht aufsteigend nach Zahlenwerten.
also bitte den "Sort" einfach wegdenken. Ist nicht wesentlich. [/Edit]
Diese Zeilen(nummern) wiederum könnten
- in eine Textdatei "3000ZeilenNr.txt" umgeleitet/durchgereicht werden
- wenn es der FindStr-Befehl rafft, dass es auch GROSSE Zeilennummern in Textdateien geben kann (ich weiß nicht, wo da intern die MaxZeilen-Zahl festgelegt ist), dann sollte die Zeilenzahl auch mit FindStr /N herauskommen und somit die betrefende Zeile gefunden werden können.
- aber das könnte genauso lange dauern, wie auch eine FOR /F - Anweisung in der Monsterdatei benötigt, um Zeile für Zeile zu dieser Zeilennummer zu gelangen.
Egal... ist alles Schritt 2.
Zu prüfen wäre jetzt von Dir, ob Dir die Streuung der 3000 "Zufalls"-zahlen mit der oben stehenden Mimik ausreicht oder ob eine "bessere" Random()-Funktion eines anderen Tools (VBS / java / #Net / whatever) benötigt wird.
Grüße
Biber
Moin ningiser,
Und bevor ich WTHF mit 22 Mio. Zeilen mache, nehme ich mir in der Regel ein paar Minuten Zeit für die Überlegung, wie ich es mache.
Deshalb (etwas kürzer und deshalb hoffentlich verständlicher) die Klärungsfragen:
Grüße
Biber
@Biber: Wie bekomme ich deine Idee denn zum laufen?
Ich habe nichts dagegen, wenn mein Compouter auch mal was länger rechnet....
Lass uns mal nichts überstürzen... wir sind ja noch in der Klärungsphase.Ich habe nichts dagegen, wenn mein Compouter auch mal was länger rechnet....
Wäre das Problem mit einer anderen Skriptsprache denn einfacher zu lösen?
Ich denke, wie meistens hängt es eher von der Lösungsstrategie, dem Algorithmus ab.Und bevor ich WTHF mit 22 Mio. Zeilen mache, nehme ich mir in der Regel ein paar Minuten Zeit für die Überlegung, wie ich es mache.
Deshalb (etwas kürzer und deshalb hoffentlich verständlicher) die Klärungsfragen:
- wie "gleichverteilt" sollen denn die "Zufallszahlen" sein?
- Liegen die 22-Mio-Koordinaten denn irgendwie logisch sortiert vor oder bekommst Du auch eine gut durchmischte Koordinatenkonstellation, wenn Du z.B. 3.000 Zeilen en bloc nehmen würdest, meinetwegen die Zeilen 118.000 bis 120999?
- Wenn es irgendwie vermeidbar ist würde ich unbedingt das physische Erzeugen einer Quasi-Kopie der 22-Mio-Monsterdatei vermeiden. Das kann nicht schnell und kann nicht ressourcenschonend sein. 3000 Zeilen aus dem Gesamtbestand kopieren: Ja. Eine 22-Mio-minus-3000-Zeile-Kopie erzeugen - wenn es vermeidbar ist: Nein. Also: Ist die Kopie der Datei für irgendetwas anderes nötig?
Grüße
Biber
Na gut, ningiser,
ich denke, jetzt bekommen wir langsam ein Gefühl dafür, wie wir dieses gewünschte Ergebnis erzielen können.
Wenn wir zu früh (nur) darüber diskutieren, mit welchem Werkzeug und welchen Detailbefehlen-> das versperrt manchmal den Blick aufs Eigentliche.
Wenn Du mich also danach fragen würdest (sagen wir mal abends in der Kneipe in noch entspannterer Atmosphäre als hier), wie ich diese Kuh vom Eis bekommen wollte, würde ich auch vor dem ersten Becks schon antworten:
Fertig is'.
Ohne da 3000x eine Randomize-Arie aufzurufen und ohne 22 Mio.Zeilen von A nach B zu kopieren.
Unelegant, aber vor dem Abendessen fertig.
Und wir Bremer essen zeitig.
Grüße
Biber
ich denke, jetzt bekommen wir langsam ein Gefühl dafür, wie wir dieses gewünschte Ergebnis erzielen können.
Wenn wir zu früh (nur) darüber diskutieren, mit welchem Werkzeug und welchen Detailbefehlen-> das versperrt manchmal den Blick aufs Eigentliche.
Wenn Du mich also danach fragen würdest (sagen wir mal abends in der Kneipe in noch entspannterer Atmosphäre als hier), wie ich diese Kuh vom Eis bekommen wollte, würde ich auch vor dem ersten Becks schon antworten:
- ich würde ein Cmd-Fenster im Verzeichnis der 22-Mio-Zeilen-Monsterdatei öffnen.
- dort einen einzigen Befehl losjagen:
findstr "1.2.3.4." 22MioMonster.txt >MiniMonster.txt
- d.h. alle Datensätze, die den Text ["1"-beliebigesZeichen-"2-beliebigesZeichen-"3"-...."] enthalten, werden aus der großen in eine kleine Datei geschrieben.
- dort sind dann, wenn ich in Statistik für Quereinsteiger damals richtig aufgepasst habe, roundabout 12000 Sätze gelandet in ebensovielen Zeilen.
- diese Zeilen Zählen wir einmal durch mit "Findstr /n $ minimonster.txt"
- wenns mehr als 3000 Zeilen sind--> nehmen wir die ersten (oder letzten) 3000 davon (mit "more +x")
- wenn es weniger sind, hängen wir noch ein Sätze dran mit [findstr "9.8.7.6." 22MioMonster.txt >>MiniMonster.txt]
Fertig is'.
Ohne da 3000x eine Randomize-Arie aufzurufen und ohne 22 Mio.Zeilen von A nach B zu kopieren.
Unelegant, aber vor dem Abendessen fertig.
Und wir Bremer essen zeitig.
Grüße
Biber
Moin ningiser,
wenn (falls!) ich Deine Aussage
Habe ich so interpretiert, dass auch Werte dabei sind wie..
Muss ja nicht sein, dass wir ein 8-Stelliges Zufallsmuster der Form "1x2x3x4x" rausfiltern.
--> ein 2 Zeichen kürzerer Matchwert würde auch besser gehen bzw streuen.
Wir können ebenso statt nach "1234" oder "4711" nach Zufallszahlen suchen
--> aber nicht mehr über die aufwändige Krücke "Zufallszahl soll gleich sein der Zeillennummer".
Denn wenn ich die zufällig ermittelte Zeilennummer 17Mio300001 aus der Datei lesen muss, dann muss ich erst 17Mio300000 (über)lesen, bevor ich irgendetwas sinnvolles -nämlich das Kopieren dieser Zeile- beginnen kann.
Das wollte ich vermeiden.
Natürlich ist es NICHT gleichverteilt -- okay.
Aber ich decke den gesamten Bereich von 5Mio865Tausend bis 5Mio870Tausend ab. und dass die 3te Nachkommastelle halt bei meiner Mimik immer eine "4" ist.... okay.
Irgendwas geht immer im Rauschen unter.
Für das Ziel "3000 Koordinaten aus dem Wertebereich von-bis aus insgesamt 22 Mio vorhandenen zufällig ermittelt" sollte es reichen.
Grüße
Biber
wenn (falls!) ich Deine Aussage
also in einem Wertebereich auf der X-Achse von 5865000.000 bis 5870000.000.
...nicht zu blauäugig aufgenommen habe, dann stehet do irgenwo in jeder Zeile minimal ein X-Wert zwischen5865000.000
....
5870000.000
Habe ich so interpretiert, dass auch Werte dabei sind wie..
5865000.000
...
5865102.304 -->passt
5865112.354 --> passt
5865122.304 --> dto
5877132.374 dto
....
5865192.394 dto
5886192.394 dto
Muss ja nicht sein, dass wir ein 8-Stelliges Zufallsmuster der Form "1x2x3x4x" rausfiltern.
--> ein 2 Zeichen kürzerer Matchwert würde auch besser gehen bzw streuen.
Wir können ebenso statt nach "1234" oder "4711" nach Zufallszahlen suchen
--> aber nicht mehr über die aufwändige Krücke "Zufallszahl soll gleich sein der Zeillennummer".
Denn wenn ich die zufällig ermittelte Zeilennummer 17Mio300001 aus der Datei lesen muss, dann muss ich erst 17Mio300000 (über)lesen, bevor ich irgendetwas sinnvolles -nämlich das Kopieren dieser Zeile- beginnen kann.
Das wollte ich vermeiden.
Natürlich ist es NICHT gleichverteilt -- okay.
Aber ich decke den gesamten Bereich von 5Mio865Tausend bis 5Mio870Tausend ab. und dass die 3te Nachkommastelle halt bei meiner Mimik immer eine "4" ist.... okay.
Irgendwas geht immer im Rauschen unter.
Für das Ziel "3000 Koordinaten aus dem Wertebereich von-bis aus insgesamt 22 Mio vorhandenen zufällig ermittelt" sollte es reichen.
Grüße
Biber
Moin ningiser,
na siehst Du... und wir haben noch keine einzige Rnd() oder Zufallszahl()-Methode gebraucht und kein Byte Batch oder VBScript oder #.net-Geraffel.
Aber weniger haarspalterisch: nach "Punkt"en im Text kannst Du auch suchen, wenn Du sie maskierst mit einem vorangestellten "\"
--> findstr "12.34" --> sucht nach "12"-ein beliebiges Zeichen-"34"
--> findstr "12\.34" --> sucht nach "12.34"
--> findstr "1.\..4" --> sucht nach "1"-ein beliebiges Zeichen-Punkt-ein beliebiges Zeichen-"4"
Oder Forumssuche im Bereich Batch & Shell nach "random" oder "Zufallszahl"
Muss doch nicht. Wir können die auch logisch ausschliessen statt physisch.
Alle Zeilen, die "logisch" nicht mehr dazugehören, haben wir doch in der kleineren "minimonster.txt".
Was brauchen wir mehr.
[Aber: wenn es partout sein müsste: Einfach den vorher verwendeten FindStr-Befehl, der in die "minimonster.txt" umgelenkt wurde, nochmals verwenden mit Parameter /v [Alle Zeilen, die NICHT enthalten..] und umlenken in "MonsterMinus3000.txt"
Ist aber IMHO Dönekens.
]
Was ich nicht aus dem Kopf beantworten kann ist die Frage nach den TABs... keine Ahnung.
Könnte sich auch maskieren lassen... hab ich noch nie versucht.
Vielleicht liest einer mit, der es mal gebraucht hat und weiss, wie es geht.
Grüße
Biber
na siehst Du... und wir haben noch keine einzige Rnd() oder Zufallszahl()-Methode gebraucht und kein Byte Batch oder VBScript oder #.net-Geraffel.
Punkte werden im Findstring als "Joker" verwendet, richtig?
Yepp.Wie kann ich dann nach Punkten, die die Nachkommastellen in der Textdatei definieren suchen lassen, oder geht das nicht?
Oder-Fragen beantworte ich immer mit "Selbstverständlich." oder "Auf keinen Fall."Aber weniger haarspalterisch: nach "Punkt"en im Text kannst Du auch suchen, wenn Du sie maskierst mit einem vorangestellten "\"
--> findstr "12.34" --> sucht nach "12"-ein beliebiges Zeichen-"34"
--> findstr "12\.34" --> sucht nach "12.34"
--> findstr "1.\..4" --> sucht nach "1"-ein beliebiges Zeichen-Punkt-ein beliebiges Zeichen-"4"
Super waere es, wenn ich die von mir vorgegebenen Nachkommastellen durch einzelne Zufallsziffern ersetzen koennte...
Mach doch. Am Cmd-Prompt hast Du dafür %random%--> siehe Hilfe "Set /?" oder "cmd /?"Oder Forumssuche im Bereich Batch & Shell nach "random" oder "Zufallszahl"
Ach ja, und die herausgelesenen Zeilen sollten am Ende in der 22Mio Monsterdatei hinterher eigentlich nicht mehr enthalten sein.
Weil....?????Muss doch nicht. Wir können die auch logisch ausschliessen statt physisch.
Alle Zeilen, die "logisch" nicht mehr dazugehören, haben wir doch in der kleineren "minimonster.txt".
Was brauchen wir mehr.
[Aber: wenn es partout sein müsste: Einfach den vorher verwendeten FindStr-Befehl, der in die "minimonster.txt" umgelenkt wurde, nochmals verwenden mit Parameter /v [Alle Zeilen, die NICHT enthalten..] und umlenken in "MonsterMinus3000.txt"
Ist aber IMHO Dönekens.
]
Was ich nicht aus dem Kopf beantworten kann ist die Frage nach den TABs... keine Ahnung.
Könnte sich auch maskieren lassen... hab ich noch nie versucht.
Vielleicht liest einer mit, der es mal gebraucht hat und weiss, wie es geht.
Grüße
Biber
Moin ningiser,
noch ein winziger Nachtrag zu der "Suche nach Tabs"
Geht nicht wirklich/wirklich nicht, aber lässt sich umgehen..
... --> soll heißen: nach dem "330" darf genau EIN Zeichen folgen (unser <tab> ) dann werden gefunden:
Sollte reichen, weil ja alle anderen Postionen durch die beiden Dezimal-Punkte "\." eindeutig verankert sind.
Grüße & schönes Wochenende
Biber
noch ein winziger Nachtrag zu der "Suche nach Tabs"
Geht nicht wirklich/wirklich nicht, aber lässt sich umgehen..
findstr "58....\.330.684....\.330" m:\eine\Monsterdatei.csv
>findstr "58....\.330.684....\.330" m:\eine\Monsterdatei.csv
581234.330 6840000.330
582345.330 6849999.330
Sollte reichen, weil ja alle anderen Postionen durch die beiden Dezimal-Punkte "\." eindeutig verankert sind.
Grüße & schönes Wochenende
Biber