Parse textfiles

Summary

Sometimes, importing hundreds of files with millions of lines of text, will take too much time. Maybe the parsing-technique could be enhanced to make that faster. Here is my code, that I do put into a compiled component, to achieve a faster text-parse, even while developing.

If this code is faster than yours; I’d like to know. If your code is faster than mine, I’d appreciate you would tell me. Either way, update me by mail.


Manchmal muß ich hunderte Dokumente mit Millionen Zeilen, erst in Datensätze und dann in Felder zerlegen, um dann meine Daten mit den angelieferten zu aktualisieren. Verschiedene Techniken den Text zu analysieren sind möglich. Hier stelle ich meinen Code vor. Während der Entwicklung brauche ich diesen Code nicht mehr zu debuggen. Also kompiliere ich diesen Code in eine Komponente und komme wesentlich schneller zu Potte.

Hier im Einsatz. Document in einem Rutsch in eine Textvariable. Den Text in Zeilen zerlegen und anschließend jede Zeile in ihre Felder. Die Feld- und Datensatztrenner werden als $3 und $4 übergeben. Statt end of file setze ich „****“.
$parseText:=Document to text($path;$encoding;Document unchanged)
ARRAY TEXT($t_textRows;0)
DBZ_Line_2Array ($parseText;->$t_textRows;“\r“;“****“)
$parseText:=““
$N:=Size of array($t_textRows)
For ($i;1;$N)
If (($i=1) & ($hasHeaderRow_b)) // Check for Header information
ARRAY TEXT($t_fieldNames;0)
DBZ_Line_2Array ($t_textRows{$i};->$t_fieldNames;“\t“;“\r“)
Else
ARRAY TEXT($t_textFields;0)
DBZ_Line_2Array ($t_textRows{$i};->$t_textFields;“\t“;“\r“)
For ($j;1;Size of array($t_textFields))
// create or update a record
// convert text into fields
End for
End if
End for

Das Verfahren hat einen Nachteil: jedes Zeichen wird zweimal geparsed, einmal um die Datensätze zu erhalten und danach um aus einem Datensatz die Felder zu extrahieren. Ich war zu faul, die Methode so auszubauen, daß ich in einem Rutsch Datensätze und Felder zerlege. Kompiliert hat es mich bisher nicht gejuckt und es ist so gut zu debuggen.

Den Code für DBZ_Line_2Array finden Sie im Anhang.

Bei Millionen Zeilen in der Summe, habe ich mir DBZ_Line_2Array in eine compilierte Komponente ausgelagert. Die liegt hier für V14


Importing textfiles and converting lines into records and line parts into fields might take some time. May be the parsing technique used could be faster.

Implementation is like this. First I put the document into a textvariable. Then I split the rows into Arrays and finally each array row into fields. Field- and record-delimiter are given as $3 and $4. Instead of end of file I set „****“.
$parseText:=Document to text($path;$encoding;Document unchanged)
ARRAY TEXT($t_textRows;0)
DBZ_Line_2Array ($parseText;->$t_textRows;“\r“;“****“)
$parseText:=““
$N:=Size of array($t_textRows)
For ($i;1;$N)
If (($i=1) & ($hasHeaderRow_b)) // Check for Header information
ARRAY TEXT($t_fieldNames;0)
DBZ_Line_2Array ($t_textRows{$i};->$t_fieldNames;“\t“;“\r“)
Else
ARRAY TEXT($t_textFields;0)
DBZ_Line_2Array ($t_textRows{$i};->$t_textFields;“\t“;“\r“)
For ($j;1;Size of array($t_textFields))
// create or update a record
// convert text into fields
End for
End if
End for

This way of parsing has a serious flaw: I’m parsing the text twice, firstly to split the records and secondly to split the fields of a record. Suppose I was to lazy to build a better version, parsing into records and fields in one go. As the way it is, is fast enough and easy to debug.

The code for DBZ_Line_2Array just below of here

For millions of lines of text, I used a compiled component with just DBZ_Line_2Array. The component for V14 as download


And here my parsing code, content of DBZ_Line_2Array