Array abarbeiten

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14726
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 24 Mal
Danksagung erhalten: 95 Mal
Kontaktdaten:

Re: Array abarbeiten

Beitrag von Jan »

Otto,

das verstehe ich jetzt nicht. Wo liegt denn der Unterschied ob ich eine csv appende oder ein Array? Da dürfte ja vermutlich das Array schneller sein, weil das dir die DataObjects schon vorbereitet ist mit den Feldern, in die die Werte geschrieben werden müssen. Bei der csv muß ich das erst auslesen, wohin welcher Wert gehört.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
azzo
1000 working lines a day
1000 working lines a day
Beiträge: 574
Registriert: So, 28. Mär 2010 19:21
Hat sich bedankt: 3 Mal
Danksagung erhalten: 17 Mal

Re: Array abarbeiten

Beitrag von azzo »

Hallo Jan,
Da ich momentan an meinem php4dbf arbeite, habe ich mich intensiv mit dem DBF-Format beschäftigt. Es ist so, dass DBF-Dateien die Felder in einem festgelegten Format speichern. Jeder Datensatz (Record) in der Datei hat immer die gleiche Länge. Das erste Zeichen eines jeden Datensatzes ist für gelöschte Datensätze reserviert, danach folgen die Felder, die so viel Platz einnehmen, wie bei der Erstellung der DBF-Datei (Create-Befehl) vorgegeben wurde.
Am Anfang der DBF-Datei befindet sich der Header, in dem unter anderem die Feldlängen und die Anzahl der Datensätze definiert sind. Die Datensätze beginnen dann nach diesem Header, wobei das Offset den Anfang eines Datensatzes angibt. Möchte man auf einen bestimmten Datensatz zugreifen, nimmt man das Offset des ersten Datensatzes und multipliziert die Datensatznummer mit der Satzlänge.

Ich denke, der append-Befehl erstellt den Datensatz (zum Beispiel aus einer CSV) und fügt diesen als Ganzes in einem Schreibvorgang in die DBF-Datei ein. Wenn man hingegen Felder einzeln hinzufügt, kann dies zu mehreren Schreibvorgängen führen.

Wenn man sich etwas mit DBF-Dateien beschäftigt, wäre es auch möglich, mehrere Datensätze als String zusammenzubauen und diese dann in einem Schritt in die DBF-Datei zu schreiben. DBF-Dateien sind allerdings keine reinen Textdateien, sondern enthalten auch binäre Formate, insbesondere für numerische und Datumstypen. Nach dem Einfügen von Datensätzen muss man im Header der DBF-Datei die Anzahl der Datensätze und das Änderungsdatum aktualisieren. Das ist dann wirklich Highspeed.

Werden bei deinem Einfügen auch Indexdateien mitaktualisiert? Das braucht auch viel Zeit.

LG
Otto
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14726
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 24 Mal
Danksagung erhalten: 95 Mal
Kontaktdaten:

Re: Array abarbeiten

Beitrag von Jan »

Hallo Otto,

wie soll ich denn eine csv-Zeile in einem Schreibvorgang in die dbf bekommen? Mal abgesehen davon das ich dann erst mal das Array in die csv schreiben muß, was ja auch etwas Zeit kostet.

Mit dem DO habe ich ja die Daten schon im korrekten Format mit den passenden Feld-und-Werte-Verknüpfungen. Und wenn Alaska diesen oder nächsten Monat das GATHER korrigiert hat wird das die erste Option sein, die ich da testen werde,

Und nein, die dbf hat zwar eine cdx, die ich aber aus genau diesem Grund nicht öffne in diesem Prozess.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
azzo
1000 working lines a day
1000 working lines a day
Beiträge: 574
Registriert: So, 28. Mär 2010 19:21
Hat sich bedankt: 3 Mal
Danksagung erhalten: 17 Mal

Re: Array abarbeiten

Beitrag von azzo »

Hallo Jan,
hier ein Beispiel.
LG
Otto

Code: Alles auswählen


FUNCTION Append5Records( cFilename )
    	LOCAL aFieldDesc, nRecordLen, cAllRecords
  	LOCAL nNewRecordCount
   	LOCAL hFile
    // Öffne die DBF-Datei im Schreibmodus
    USE ( cFilename ) EXCLUSIVE

    // Hole das Header
     
    nRecordLen := RECSIZE()   // Länge des Datensatzes

    // Berechne die Headergröße (Standardmäßig 32 Bytes + 32 Bytes pro Feld)
    nHeaderSize := HEADER()   // Größe des Headers der DBF-Datei

    // 5 konkrete Adressdatensätze als String mit Lösch-Flag
    cAllRecords := " " + "Mustermann   Max         Musterstr. 1  Musterstadt " + ;
                   " " + "Schmidt      Anna        Beispielweg 2 Beispielstadt" + ;
                   " " + "Meier        Lukas       Hauptstr. 3   Hauptstadt  " + ;
                   " " + "Klein        Laura       Nebenweg 4    Nebenstadt  " + ;
                   " " + "Fischer      Paul        Anglergasse 5 Anglerdorf  "

    // Öffne die Datei und gehe zur Position nach dem letzten Datensatz
    hFile := FOPEN( cFilename, FO_READWRITE )
    FSEEK( hFile, nHeaderSize + RECCOUNT() * nRecordLen, FS_SET )

    // Schreibe alle Datensätze in einem Schritt in die Datei
    FWRITE( hFile, cAllRecords )
    
    // Aktualisiere den Header mit der neuen Datensatzanzahl
    nNewRecordCount := RECCOUNT() + 5
    FSEEK( hFile, 4, FS_SET )
    FWRITE( hFile, LTOC( nNewRecordCount, 4 ) )

    // Datei schließen
    FCLOSE( hFile )
    CLOSE




In einer DBF-Datei gibt es kein spezielles End-of-Text-Zeichen (EOT) wie in manchen anderen Dateiformaten. Stattdessen basiert das Ende der Datei auf der definierten Anzahl von Datensätzen im Header.

Der Header enthält Informationen über die Anzahl der Datensätze, die die Software nutzt, um zu bestimmen, wann das Ende der Datei erreicht ist. Ein zusätzliches Zeichen wie EOT wird daher nicht benötigt oder erwartet.

Es ist wichtig, dass der Header nach dem Hinzufügen von Datensätzen korrekt aktualisiert wird, damit die DBF-Datei konsistent bleibt. Dein Code macht dies bereits durch das Aktualisieren der Anzahl der Datensätze.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14726
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 24 Mal
Danksagung erhalten: 95 Mal
Kontaktdaten:

Re: Array abarbeiten

Beitrag von Jan »

Hallo Otto,

danke für das Beispiel. Das macht manches klarer was Du meinst. Aber:

1) Das ist ja keine csv. Sondern einfach ein langer String. Den ich aber natürlich sehr einfach erstellen könnte aus dem Array.

2) So einfach scheint das aber nicht zu sein. Wenn ich solch eine dbf im Editor öffne und Sonderzeichen anzeigen lasse, dann sehe ich am Beginn jedes Satzes verschiedene Zeichenketten:
NULNULNUL
STXNULNUL
ETXNULNUL
NULNUL (die häufigste Variante)
BELNULNUL
EOTNULNUL
EOQNULNUL
ACKNULNUL
BSNULNUL
SOHNULNUL
NULNUL (ja, eine Lücke zu Beginn)
usw.
Ebenso gibt auch mitten in einem Satz solche Sonderzeichen. Dann auch häufig mehrere, bei einem kurzen Überblick habe ich bis zu 12 am Stück gefunden. Größtenteils NUL, aber vereinzelt auch andere.

3) Und wie bekomme ich die Inhalte von Memofeldern da rein? Ich habe sowohl Text-Memos als auch binäre Memofelder da drin.

Wie gesagt, der Ansatz ist ganz interessant, und ich sehe ein daß das rattenschnell sein müsste - wenn es denn wirklich funktionieren würde.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
azzo
1000 working lines a day
1000 working lines a day
Beiträge: 574
Registriert: So, 28. Mär 2010 19:21
Hat sich bedankt: 3 Mal
Danksagung erhalten: 17 Mal

Re: Array abarbeiten

Beitrag von azzo »

hallo Jan,

Hier mein PHP-append-Funktion:

Code: Alles auswählen


function php4dbf_appendBlank($filename, $loggingEnabled = true) {
    $dbf = php4dbf_openDbf($filename, $loggingEnabled);
    $header = php4dbf_getDbfHeader($dbf, $loggingEnabled);
    $fields = php4dbf_getFieldDescriptors($dbf, $loggingEnabled);
    $recordLength = php4dbf_calculateRecordLength($fields);

    // Construct record data with default values based on field type
    $recordData = ' '; // Start with a space for the deletion flag
    foreach ($fields as $field) {
        // Set default values based on field type
        switch ($field['type']) {
            case 'C': // Character type
                $paddedValue = str_repeat(' ', $field['length']); // Fill with spaces
                break;
            case 'N': // Numeric type
                $paddedValue = str_pad('0', $field['length'], '0', STR_PAD_LEFT); // Fill with zeroes
                break;
            case 'L': // Logical type
                $paddedValue = 'F'; // Default to false
                break;
            case 'D': // Date type
                $paddedValue = '        '; // 8 spaces for empty date (or optionally "  .  .    ")
                break;
            case 'M': // Memo type
                $paddedValue = str_pad('', $field['length']); // Empty memo
                break;
            default:
                $paddedValue = str_repeat(' ', $field['length']); // Default to spaces for unknown types
        }
        $recordData .= $paddedValue;
    }

    // Ensure the record data matches the record length
    if (strlen($recordData) < $recordLength) {
        $recordData = str_pad($recordData, $recordLength);
    } else {
        $recordData = substr($recordData, 0, $recordLength);
    }

    // Determine new record position
    $recordCount = $header['recordCount'];
    $newRecordNumber = $recordCount + 1;

    $headerLength = $header['headerLength'];
    $insertPosition = $headerLength + $recordCount * $recordLength;
    fseek($dbf, $insertPosition);
    fwrite($dbf, $recordData);

    // Update the record count in the header
    fseek($dbf, 4);
    fwrite($dbf, pack('V', $newRecordNumber));

    // Update the last modification date using the new function
    php4dbf_updateLastModifiedDate($dbf, $loggingEnabled);

    fclose($dbf);
    return true;
}




Du brauchst den String nur nach diesem Schema zusammenzubauen.

Das mit den Memofeldern ist etwas komplizierter – viel komplizierter.
Hier musst du dann zuerst in die Memodatei schreiben und dann den Offset in die DBF.
Ich unterstütze das nicht in meiner php4dbf-Lib. Ich habe mich entschlossen, die Memofelder zuerst in Dateien zu exportieren und schreibe dann ins Memofeld in der DBF eine Referenz. Im Prinzip ist es ähnlich wie bei Memo, dort hast du ja auch nur eine Referenz.

Aus meiner Sicht und für meinen Gebrauch – Webanwendungen – bin ich zur Überzeugung gekommen, dass die Memodatei, wie sie bei DBF ist, überholt ist.

Heute hat man ja kein Problem mehr mit der Anzahl der Files pro Verzeichnis.

Überleg mal, wie man die Ablage mit eigenen Dateien für die Memofelder elegant lösen kann.


Die DBF ist keine Textdatei, sondern eine Binärdatei.


LG
Otto



In DBF-Dateien wird das Memo-Feld verwendet, um Textdaten zu speichern, die länger als die Kapazität eines normalen Textfeldes sind. Hier sind die wichtigsten Konzepte:

Memo-Feldstruktur: Ein Memo-Feld in einer DBF-Datei verweist auf eine externe Datei (oft mit der Endung .dbt oder .fpt), in der die eigentlichen Memo-Daten gespeichert werden. Das Feld in der DBF-Datei selbst enthält nur einen Zeiger (eine Adresse oder einen Index), der auf den Speicherort der Daten in dieser externen Memo-Datei verweist.

Memo-Datei: Die Memo-Datei wird parallel zur DBF-Datei geführt. Sie enthält die eigentlichen Memo-Daten, also z.B. lange Textbeschreibungen. Diese Datei ist in Blöcke unterteilt, und jeder Block kann Daten eines einzelnen Memo-Feldes speichern.

Verweis im Memo-Feld: Anstelle der eigentlichen Textdaten wird im Memo-Feld der DBF-Datei eine Referenz gespeichert (normalerweise eine Blocknummer oder ein Offset), die angibt, wo sich die Daten in der Memo-Datei befinden.

Größe und Verwaltung: Da die Größe der Textdaten in einem Memo-Feld variabel ist, kann ein Memo-Feld viel mehr Daten aufnehmen als normale Felder. Allerdings macht dies das Speichern und Verwalten von Memos auch komplexer, da die DBF-Datei und die Memo-Datei synchron gehalten werden müssen.

Zusammengefasst speichert das Memo-Feld nicht direkt die Daten, sondern verweist auf eine externe Datei, in der die eigentlichen Daten gespeichert werden. Die Verwaltung und Bearbeitung dieser Felder erfordert daher den Zugriff auf beide Dateien (DBF und Memo).
ramses
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2537
Registriert: Mi, 28. Jul 2010 17:16
Hat sich bedankt: 12 Mal
Danksagung erhalten: 80 Mal

Re: Array abarbeiten

Beitrag von ramses »

@Otto

Hallo Otto

für deine Aufgaben der "Web-Programm Entwicklung" von denen du hier immer schreibst müsstest du dir eigentlich WebDev einmal genauer ansehen und damit etwas "rummachen". Da sind viele Dinge mit denen sich du und alle andern mit den xbase Dialekten täglich rumqälen einfach vorhanden und funktionieren auf Anhieb absolut problemlos und sind sogar gut dokumentiert. Das Teil kann auch PHP Code gererieren und die so erstellen Programme laufen auch auf Linux ... und die Entwicklung ist einer APP ist zudem mindestens 20 mal schneller und einfacher als unter Xbase++, Harbour etc. ....
Valar Morghulis

Gruss Carlo
Benutzeravatar
azzo
1000 working lines a day
1000 working lines a day
Beiträge: 574
Registriert: So, 28. Mär 2010 19:21
Hat sich bedankt: 3 Mal
Danksagung erhalten: 17 Mal

Re: Array abarbeiten

Beitrag von azzo »

Hallo Carlo,
ich habe es schon erwähnt. WinDev hat in etwa die gleiche User-Struktur wie Xbase und Harbour.
Ich sehe einfach keinen Nachwuchs. Auch die eigene Programmiersprache gefällt mir nicht, bzw. du brauchst auch eigene WinDev-Webserver.
Du wirst auch kaum qualifizierte Hilfe, wie bei PHP, HTML und JS erhalten. Diesen Source Code schreibt die AI schon weitgehend fehlerfrei.
AI ist hier disruptiv für Anwendungen, wo wenig Trainingsdaten verfügbar sind. Leider.

LG
Otto
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15740
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 77 Mal
Danksagung erhalten: 41 Mal
Kontaktdaten:

Re: Array abarbeiten

Beitrag von brandelh »

musst du alle Einträge des Array sequenziell bearbeiten ?
dann ist aeval() die schnellste Lösung, auch wenn es keine Welten zu for next sind.

Wenn dein Array aber nach dem ersten Element durchsucht werden muss um dann auf das zweite zuzugreifen, dann sind Arrays langsam.
Paplo hat für diesen Zweck eine eigene Klasse gemacht, der Name ist mir aber entfallen
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14726
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 24 Mal
Danksagung erhalten: 95 Mal
Kontaktdaten:

Re: Array abarbeiten

Beitrag von Jan »

Leute,

seid mir nicht böse. Aber können wir diese Diskussion jetzt hier beenden? Ich bin allen Dankbar für Eure Ideen und Vorschläge. Einen Vorschlag habe ich abgewandelt übernommen. Bei anderen habe ich erklärt warum das so nicht geht oder nicht sinnvoll ist. Dann gab es noch zwei Vorschläge wie das grundsätzlich anders geht. Einer geht nicht aus technischen Gründen, beim anderen gibt es auf meine Rückfrage noch keine Antwort. Aber auch diese Vorschläge haben natürlich Mehrwert, weil die Gedanken in den Kopf setzen zum weiterdenken. Das ist ja auch mit der Sinn solcher Diskussionen hier im Forum, und ich bin dankbar wenn solch erheblich unterschiedlichen Ideen zusammen kommen. Weil die oftmals neue Horizonte eröffnen.

Jetzt aber immer wieder die gleichen Ideen noch mal zu nennen, oder Diskussionen um Wettbewerbsprodukte zu führen, oder bereits verworfene Ideen noch mehr zu vertiefen, führt hier überhaupt nicht weiter.

Wie gesagt, bitte nicht böse sein. Wir können manche der Dinge auch gerne weiter diskutieren, dann aber eben nicht in diesem Thread. Sondern in einem neuen, in dem es speziell um die dort besprochenen Themen oder Lösungsansätze geht. Und wo dann vielleicht auch andere Forenteilnehmer mit diskutieren, die an dem eigentlichen Thema hier im Thread eigentlich kein Interesse haben.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Antworten

Zurück zu „Programmierung allgemein“