DBF-Typ bestimmen ...

Zugriff, Engines, Konvertierung. Von ADS über DBF bis zu SQL.

Moderator: Moderatoren

Antworten
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

DBF-Typ bestimmen ...

Beitrag von brandelh »

Hallo,

DBFs gibt es ja in den verschiedensten Ausführungen (dbase3ff (inkl. Clipper und Xbase) mit und ohne DBT und von Foxpro ff.).
Je nach Art, muß man DBFDBE oder FOXDBE benutzen, wobei bei falscher Wahl ein Runtimeerror erfolgt. Die ersten beiden Byte einer DBF geben ja über den Typ auskunft. Hat schon jemand eine Funktion geschrieben, die zumindest die richtige DBE (DBF oder FOX) bestimmen kann ?

Ist ja nicht schwer, aber bevor ich mich da reinhänge frage ich doch mal. ;)

PS: DBINFO() und DBEINFO() funktionieren ja erst nach dem Öffnen, ich möchte die Infos aber bei geschlossener Datei !
Gruß
Hubert
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Re: DBF-Typ bestimmen ...

Beitrag von Martin Altmann »

Hallo Hubert,
brandelh hat geschrieben:ich möchte die Infos aber bei geschlossener Datei !
sowas wird noch keiner geschrieben haben :lol: :wink:

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14655
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Beitrag von Jan »

Martin,

ich denke Hubter meinte, bei per DBE geöffneter Datei. Denn da können schließlich schon die ersten Probleme auftauchen, wenn der falsche Treiber dafür genutzt wird.

Ein sonstiges Öffnen zwecks Ansehen der betreffenden Bytes sollte dagegen nicht das große Problem sein.

Jan
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Jan,
ist mir schon klar - ich konnte mir den Kommentar nur nicht verkneifen (darum auch den :wink: am Ende).
Bin halt heut' ein wenig albern - heut' ist der erste Tag meiner Nachtschicht, da muss ich mich noch ein wenig in gute Stimmung bringen :)

Viele Grüße,
Maritn
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14655
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Beitrag von Jan »

Martin,

[offtopic] Nachtschicht in der Bank? Ich dachte sowas hätten nur die Bankräuber, nicht die Bankmitarbeiter?[/offtopic]

Jan
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Jan,
am Ende des Tages läuft ja die Verarbeitung aller Transaktionen über die Nacht hindurch.
Und da werden die kritischen Prozesse natürlich überwacht und auch eingegriffen, sofern nötig.
Da ja auch bei uns eingespart werden soll, wird halt mit wenig Personal gearbeitet. Und wenn von den zuständigen Kollegen auch mal einer Urlaub machen will, dürfen halt auch andere mal ran.

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: DBF-Typ bestimmen ...

Beitrag von brandelh »

Martin Altmann hat geschrieben:Hallo Hubert,
brandelh hat geschrieben:ich möchte die Infos aber bei geschlossener Datei !
sowas wird noch keiner geschrieben haben :lol: :wink:

Viele Grüße,
Martin
Hallo Martin,

krieg dich wieder ein vor lachen, ich meine was ich schreibe. ;)

Natürlich muß ich mir mit fopen, fread, fclose die Infos besorgen, aber dabei kann ja nichts schief gehen, solange die DBF überhaupt vorhanden ist - insoweit war ich etwas ungenau.
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14655
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Beitrag von Jan »

Martin,

Nachtschicht heißt also: Zurücklehnen, Däumchen drehen, bis irgendwo mal vielleicht eine rote Lampe aufleuchtet? Toller Job, nichts für mich! Aber wenn Du das auch nur zur Vertretung und nicht ständig machen mußt, dann geht das ja gerade noch.

Jan
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16517
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 111 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Jan,
leider nicht ganz. Es sind Laufzeiten zu überwachen und zu protokollieren und ggf. Telefonate zu führen (auch mit London oder New York).
Wenn also alles glatt geht, ist man nur mit schreiben und logfiles prüfen beschäftigt und hat dann und wann auch mal 10 Minuten Zeit, sich einen Tee zu holen oder wegzubringen.
Aber sobald es irgendwo knallt, wird es hektisch. Und wenn dann noch mehr knallt, weiß man nicht, was man zuerst machen soll... :roll:

Hubert,
war mir ja schon klar, wie Du das eigentlich meintest :)
Hast Du schon mal hier geschaut?

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Martin Altmann hat geschrieben:Hast Du schon mal hier geschaut?
Für TurboBasic habe ich vor 15 Jahren mal eine Funktionssammlung für die Verwaltung von Daten in DBF geschrieben. Von daher habe ich noch recht gute Infos vom Dateiheader, wobei ich heute aus Sicherheitsgründen hingehen werde und mit der DBFDBE und der FOXDBE halt die verschiedenen möglichen DBFs erzeuge (OEM und ANSI) und nachsehe, was im DBF Type eingetragen ist. Eventuell hat ja Alska auch noch was hinzugefügt ;)

Ich komme drauf, weil ich mich immer tierisch ärgere, wenn ich den DBEDITOR aufrufe und entscheiden soll was es jetzt für eine DBF ist, ohne Indexe (NTX/CDX) und Memofeld ist es gar nicht möglich, ansonsten nicht wirklich sicher. Eine Funktion könnte das ein für alle mal erledigen, ich denke ich werde mal anfangen ...
Gruß
Hubert
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2470
Registriert: Fr, 23. Dez 2005 8:00
Wohnort: Aalen
Hat sich bedankt: 102 Mal
Danksagung erhalten: 3 Mal
Kontaktdaten:

Beitrag von Koverhage »

Hallo Hubert,

schau mal auf die Seite von Phil Ide, der hat dort doch so ein Programm in Xbase++ gemacht, welches den Header ausliest und alle Infos anzeigt. Das könnte man doch nutzen.
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2470
Registriert: Fr, 23. Dez 2005 8:00
Wohnort: Aalen
Hat sich bedankt: 102 Mal
Danksagung erhalten: 3 Mal
Kontaktdaten:

Beitrag von Koverhage »

Die web adresse siehst Du hier unter links und demos ;-)
mr@nline.de
Cut&Paste-Entwickler
Cut&Paste-Entwickler
Beiträge: 37
Registriert: Do, 19. Okt 2006 10:24
Wohnort: St. Martin

Beitrag von mr@nline.de »

Hallo Hubert,
ich habe da eine Klasse "DBFCLASS", mir der kannst Du ohne DBE
die Tabelle öffnen und lesen, habe ich schon öffters benötigt um
Daten aus einer defekten Tabelle wieder herauszuholen.
Ich denke die Information steht in irgend einem Byte im Header.
Auf jeden Fall kannst Du mit dieser Klasse und etwas Anpassung
alle Informationen "low level" lesen.

Code: Alles auswählen

//----------
// Beispiel
//----------
oDbf := dbfclass():new("m:\temp\rechnung.dbf"):create()
oDbf:dbopen()
oDbf:dbgotop()
do while ! oDbf:eof()
    xVal := odbf:ReadFieldbyNum(n)
    odbf:dbskipnext(+1)
enddo
odbf:dbclose()




#include "Xbp.ch"
#include "komet.ch"
#include "directry.ch"
#include "class.ch"
#include "Fileio.ch"

//--------------------
// DBF-Tabellen Klasse
//--------------------
CLASS DBFCLASS

 PROTECTED:

 EXPORTED:
   VAR nH              // Tabellenhandle
   VAR nHMemo          // Memofeldhandle
   VAR cFile           // Filename
   VAR cFileMemo       // Filename Memo
   VAR nSize           // Tebellengröße
   VAR nRecs           // Anzahl Datensätze aus der Headerinfo
   VAR nLastrec        // Anzahl Datensätze
   VAR nHeadersize     // Größe des Dateiheaders
   VAR nRecsize        // Größe eines Datensatzes
   VAR cHeader         // Dateiheader
   VAR nMemoblockSize  // Größe des Memoblockes
   VAR nTypeMemo       // MEO-format 1=DBT 2=FPT
   VAR cRecord         // Inhalt des aktuelln Datensatzes
   VAR nRecord         // Aktuelle Datensatznummer
   VAR nMaxField       // Maximale Feldanzahl
   VAR aFields         // Array mit Feldinformationen
   VAR cLastField      // Name des zuletzt zugefriffenen Feldes
   VAR nLastField      // Nummer des zuletzt zugegriffenen Feldes
   VAR lEof            // Eof-Status
   VAR lBof            // Bof-Status
   VAR cCache          // ReadCache Puffer
   VAR nCacheRec       // ReadCache Recordanzahl
   VAR nCacheRecFirst  // Erster Datensatz im Cache
   VAR nCacheRecLast   // Letzter Datensatz im Cache

   //----------------------
   // Object initialisieren
   //----------------------
   INLINE METHOD init(cFile)
       ::nH             := 0
       ::nHMemo         := 0
       ::nSize          := 0
       ::nRecs          := space(4)
       ::nLastrec       := 0
       ::nHeadersize    := space(2)
       ::nRecsize       := space(2)
       ::cHeader        := ""
       ::nRecord        := 0
       ::nMaxField      := 0
       ::aFields        := {}
       ::cLastField     := ""
       ::nLastField     := 0
       ::nMemoBlockSize := 0
       ::nTypeMemo      := 0
       ::cFile          := ltrim(trim(cFile))
       ::lEof           := .f.
       ::lBof           := .f.
       ::cCache         := ""
       ::nCacheRec      := 1000
       ::nCacheRecFirst := 0
       ::nCacheRecLast  := 0


       if upper(right(::cFile,4)) != ".DBF"
          ::cfile := ::cfile +".dbf"
       endif
       //--------------------
       // Name der Memo-Datei
       //--------------------
       if file(left(::cFile,len(::cFile)-3)+"FPT")
          ::cfileMemo :=left(::cFile,len(::cFile)-3)+"FPT"
          ::nTypeMemo := 2
       elseif file(left(::cFile,len(::cFile)-3)+"DBT")
          ::cfileMemo :=left(::cFile,len(::cFile)-3)+"DBT"
          ::nTypeMemo := 1
       endif

       //? "CLass new",::cfile


   RETURN SELF


   //-----------------
   // Objekt erstellen
   //-----------------
   INLINE METHOD create()

   RETURN SELF


   //---------------
   // Objekt löschen
   //---------------
   INLINE METHOD destroy()
      if ::nH > 0
         fClose(::nH)
      endif
      ::nh := 0

      if ::nHMemo > 0
         fClose(::nHMemo)
      endif
      ::nhMemo := 0
   RETURN SELF

   //-------------------
   // Tabelle Schliessen
   //-------------------
   INLINE METHOD dbclose()
      ::destroy()
   RETURN SELF


   //---------------
   // Tabelle öffnen
   //---------------
   INLINE METHOD dbopen()
       local n := 0 ,nC := 0,cOut
       local cField,cType,nLen,nDec,cLen,cDec,cSizeM
       local nF,cOff,nOff:=0,nSizeRec:=1
       //? ::cFile,"vor öffnen.."

       ::nh := fOpen(::cFile,FO_READWRITE)
       if ::nH < 1
          ::nh := fOpen(::cFile)
       endif

       if ::nH > 0
          //? ::cFile,"offen.."
          //-------------
          // Header lesen
          //-------------
          ::nSize:= fileSize(::cFile)
          FSeek( ::nH, 4 )
          FRead( ::nH, @::nRecs, 4 )
          FRead( ::nH, @::nHeaderSize, 2 )
          FRead( ::nH, @::nRecSize, 2 )

          ::nRecs       := Bin2L( ::nRecs )
          ::nHeaderSize := Bin2W( ::nHeaderSize )
          ::nRecSize    := Bin2W( ::nRecSize )
          ::nLastRec    := int((::nSize-1-::nHeadersize)/::nRecsize)
          ::cHeader     := space(::nHeaderSize)
          ::cCache      := space(::nRecSize*::nCacheRec)
          ::nMaxfield   := int( ((::nHeaderSize-2)/32)-1 )

          //-----------------
          // Felder bestimmen
          //-----------------
          cField := ""
          nC     := 0
          nF     := 0
          fseek(::nH,0,FS_SET)
          fread(::nH,@::cHeader,::nHeadersize)
          cOut := ""
          for n:= 1 to ::nHeaderSize
              if n >32
                 nC++
              endif

              if nC==1
                 nF++
                 cField := padr(token(strtran(substr(::cHeader,n   ,10),chr(0)," "),1),10," ")
                 cType  := substr(::cHeader,n+11,01)
                 cOff   := substr(::cHeader,n+12,02)
                 if cType=="C"
                    cLen   := substr(::cHeader,n+16,02)
                    nLen   := Bin2W( cLen)
                    nDec   := 0
                 else
                    cLen   := substr(::cHeader,n+16,01)
                    cDec   := substr(::cHeader,n+17,01)
                    nLen   := Bin2L( cLen)
                    nDec   := Bin2L( cDec)
                 endif
                 //nOff   := Bin2W( cOff)+1
                 //? "Feld","["+cField+"]",cType,padl(nLen,4,"0"),padl(nDec,2,"0"),"Offset",padl(nOff+2,4,"0")
                 aaDD(::aFields,{cField,cType,nLen,nDec,nOff+2})
                 nSizeRec := nSizeRec+nLen
                 if nF==::nMaxfield
                    exit
                 endif
                 nOff := nOff + nlen
              endif
              /*
              if n <= 32
                 cOut := padl(n,4,"0")+"-"+padl(asc(::cHeader[n]),3,"0")+"["+::cHeader[n]+"]"
                 ? cOut
              endif
              */
              if nC==32
                 nC := 0
              endif
          next n
          //-----------------
          // Memodatei öffnen
          //-----------------
          if ::cFileMemo != NIL
             ::nhMemo      := fOpen(::cFileMemo,FO_READWRITE)
             if ::nHMemo < 1
                ::nhMemo      := fOpen(::cFileMemo)
             endif
             if ::nhMemo > 0
                if ::nTypeMemo==1
                   ::nMemoBlockSize  := 512
                elseif ::nTypeMemo==2
                   cSizeM := space(2)
                   FSeek( ::nHMemo, 6 )
                   FRead( ::nHMemo, @cSizeM, 2 )
                   ::nMemoBlockSize  := asc(csizeM[1])*256+asc(csizeM[2])
                endif
             endif
             //? "Memfile",::cFileMemo,::nhMemo
          endif
          /*
          ?  "[Tabelle  ]" ,::cFile
          ?  "[Header   ]" ,::nHeadersize
          ?  "[Recsize  ]" ,::nRecSize
          ?  "[Felder   ]" ,::nMaxField
          ?  "[Filesize ]" ,::nSize
          ?  "[Records  ]" ,::nLastRec
          ?  "[Blocksize]" ,::nMemoBlockSize
          ?  "[Memotype ]" ,::nTypeMemo
          ? "Länge aus Feldern",nSizeRec
          */
       endif

   RETURN SELF


   //------------------------------------
   // Zu einem bestimmten Datensatz gehen
   //------------------------------------
   INLINE METHOD dbGoTo(nRec)
       local nRead

          if nRec >= ::nCacheRecFirst .and. nRec <= ::nCacheRecLast .and. ::nCacheRecfirst > 0
             //---------------------------------
             // Datensatz befindet sich im Cache
             //---------------------------------
             ::nRecord := nRec
             ::lEof    :=.f.
             ::lBof    :=.f.
          else
             if nRec < 1
                ::cCache         := space(::nRecSize*::nCacheRec)
                ::lBof           := .t.
                ::nRecord        := 0
                ::nCacheRecFirst := 0
                ::nCacheRecLast  := 0
             elseif nRec > ::nLastrec
          ? "Resize",::nRecSize

                ::cCache         := space(::nRecSize*::nCacheRec)
                ::lEof           := .t.
                ::nRecord        := 0
                ::nCacheRecFirst := 0
                ::nCacheRecLast  := 0
             else
                //----------------
                // Cache neu lesen
                //----------------
                fseek(::nH,::nHeadersize+((nRec-1)*::nRecsize),FS_SET)
                nRead := fread(::nH,@::cCache,::nRecSize*::nCacheRec)
                if nRead >= ::nRecSize
                   ::nCacheRecFirst := nRec
                   ::nCacheRecLast  := nRec + int(nRead/::nRecSize)-1
                   ::nRecord        := nRec
                   ::lEof           :=.f.
                   ::lBof           :=.f.
                else
                   ::cCache         := space(::nRecSize*::nCacheRec)
                   ::nCacheRecFirst := 0
                   ::nCacheRecLast  := 0
                   ::lEof           := .t.
                   ::nRecord        := 0
                endif
             endif
          endif

   RETURN SELF


   //-------------------
   // Zum Tabellenanfang
   //-------------------
   INLINE METHOD dbGoTop()
       ::dbGoto(1)
   RETURN SELF


   //-----------------
   // Zum Tabellenende
   //-----------------
   INLINE METHOD dbGoBottom()
       ::dbGoto(::nLastrec)
   RETURN SELF


   //---------------------------
   // Datensatz vorwärts bewegen
   //---------------------------
   INLINE METHOD dbskipNext()
       if ::nRecord < ::nLastrec
          ::dbGoto(::nRecord+1)
       else
          ::lEof :=.t.
       endif
   RETURN SELF

   //----------------------------
   // Datensatz rückwärts bewegen
   //----------------------------
   INLINE METHOD dbskipPrev()
       if ::nRecord > 1
          ::dbGoto(::nRecord-1)
       else
          ::lBof :=.t.
       endif
   RETURN SELF

   //-----------------------------------------------------------
   // aktuelle Datensatznummer ohne Berücksichtigung von Filtern
   //-----------------------------------------------------------
   INLINE METHOD Recno()
   RETURN ::nRecord

   //----------------------------------------------------
   // Anzahl Datensätze ohne Berücksichtigung von Filtern
   //----------------------------------------------------
   INLINE METHOD Lastrec()
       //--------------------
       // Größe neu bestimmen
       //--------------------
       ::nSize    := fileSize(::cFile)
       ::nLastRec := int((::nSize-1-::nHeadersize)/::nRecsize)

   RETURN ::nLastrec

   //-------------
   // EOF - Status
   //-------------
   INLINE METHOD eof()
   RETURN ::lEof

   //-------------
   // BOF - Status
   //-------------
   INLINE METHOD bof()
   RETURN ::lBof

   //-----------------
   // DELETED - Status
   //-----------------
   INLINE METHOD Deleted()
       local lDel := .f.
       if ::GetRecordAsString()[1]=="*"
          lDel := .t.
       endif
   RETURN lDel


   //-------------------------------
   // aktueller Datensatz als String
   //-------------------------------
   INLINE METHOD GetRecordAsString()
   return substr(::cCache, 1 + ((::nRecord - ::nCacheRecFirst)*::nRecSize) ,::nRecSize)

   //---------------------------------
   // Prüfen ob Feldname vorhanden ist
   //---------------------------------
   INLINE METHOD isFieldName(cField)
       local lRet := .f.
       local n
       if ::nH > 0
          cField := padr(upper(cField),10," ")
          for n:=1 to ::nMaxfield
              if ::aFields[n][1]==cField
                 lRet := .t.
                 exit
              endif
          next n
       end
   RETURN lRet

   //-------------------
   // Feldwert ermitteln
   //-------------------
   INLINE METHOD ReadFieldbyName(cField,lKonv)
       local xRet
       local n,nBlock,nRecOffSet
       if ::nH > 0
          cField := padr(upper(cField),10," ")
          if ::cLastField==cField

             nRecOffSet := ((::nRecord - ::nCacheRecFirst)*::nRecSize)
             xRet       := substr(::cCache,nRecOffSet+::aFields[::nLastField][5],::aFields[::nLastField][3])
             n          := ::nLastField
          else
             for n:=1 to ::nMaxfield
                 if ::aFields[n][1]==cField
                    nRecOffSet   := ((::nRecord - ::nCacheRecFirst)*::nRecSize)
                    xRet         := substr(::cCache,nRecOffSet+::aFields[n][5],::aFields[n][3])
                    ::cLastField := cField
                    ::nLastField := n
                    exit
                 endif
             next n
          endif
          //-----------------
          // Typkonvertierung
          //-----------------
          if lKonv==NIL
             lKonv := .t.
          endif
          if lKonv .and. xRet != NIL
             if ::aFields[n][2]=="N"
                xRet := val(xRet)
             elseif ::aFields[n][2]=="D"
                xRet := stod(xRet)
             elseif ::aFields[n][2]=="L"
                xRet := if(xRet=="T",.t.,.f.)
             elseif ::aFields[n][2]=="M"
                nBlock := val( xRet)
                ? "Block",nBlock
                if nBlock > 0
                   xRet := ::ReadMemoBlock(nBlock)
                else
                   xRet := ""
                endif
             endif
          endif
       endif
   RETURN xRet


   //-------------------
   // Feldwert ermitteln
   //-------------------
   INLINE METHOD ReadFieldbyNum(nField,lKonv)
       local xRet,nBlock,nRecOffSet

       nRecOffSet := ((::nRecord - ::nCacheRecFirst)*::nRecSize)
       xRet       := substr(::cCache,nRecOffSet+::aFields[nField][5],::aFields[nField][3])

       //-----------------
       // Typkonvertierung
       //-----------------
       if lKonv==NIL
          if ::aFields[nField][2]=="N"
             xRet := val(xRet)
          elseif ::aFields[nField][2]=="C"

          elseif ::aFields[nField][2]=="D"
             xRet := stod(xRet)
          elseif ::aFields[nField][2]=="L"
             xRet := if(xRet=="T",.t.,.f.)
          elseif ::aFields[nField][2]=="M"
             nBlock := val( xRet)
             if nBlock > 0
                xRet := ::ReadMemoBlock(nBlock)
             else
                xRet := ""
             endif
          endif
       endif
   RETURN xRet


   //-------------------
   // Memoblock auslesen
   //-------------------
   INLINE METHOD ReadMemoBlock(nBlock)
       local cRet       := ""
       local cRead      := ""
       local n          := 0
       local cSize      := Space(4)
       local nSize      := 0
       local xRead
       local xPos
       if ::nhMemo >0
          if ::nTypeMemo==1
             //----
             // DBT
             //----
             fseek(::nHMemo,0+(nBlock*::nMemoBlockSize),FS_SET)

             //------------------------------------------------------
             // Werte bis zum nächsten CTRL-Z oder Dateiende einlesen
             //------------------------------------------------------
             cRead := space(1)
             do while fread(::nHMemo,@cRead,1) > 0
                if asc(cRead)==26
                   exit
                else
                   cRet := cRet+cRead
                endif
             enddo
             cRet:=trim(cRet)

          elseif ::nTypeMemo==2
             //----
             // FPT
             //----
             xPos := fseek(::nHMemo,0+4+(nBlock*::nMemoBlockSize),FS_SET)
             xRead := fread(::nHMemo,@cSize,4)
             nSize := (asc(cSize[3]))*256+asc(cSize[4])
             //? "Size",nSize,::nMemoBlockSize,xRead,"POS",::nHMemo,0+4+(nBlock*::nMemoBlockSize),xPos
             cRet  := space(nSize)
             xRead := fread(::nHMemo,@cRet,nSize)
             //? "Gelesen",xRead
          endif
       endif
   Return cRet


ENDCLASS

Gruß
Manfred
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15697
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 66 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Beitrag von brandelh »

Hallo,

danke an alle, ich werde zu gegebener Zeit die Funktion veröffentlichen.
Gruß
Hubert
Antworten