Re: Datei binär einlesen
From: Michael Windmeier (MeikelWausPDB_at_nurfuerspam.de)
Date: 03/09/04
- Next message: Dieter Strassner: "Re: Error 1053 bei Start eines Service mit NTSVC.OCX"
- Previous message: Jens Duczmal: "Re: 2 Bilder vergleichen"
- In reply to: Peter Götz: "Re: Datei binär einlesen"
- Next in thread: Michael Windmeier: "Re: Datei binär einlesen"
- Reply: Michael Windmeier: "Re: Datei binär einlesen"
- Reply: Peter Götz: "Re: Datei binär einlesen"
- Messages sorted by: [ date ] [ thread ]
Date: Tue, 09 Mar 2004 08:54:12 +0100
"Peter Götz" <gssg_nospam@t-online.de> schrieb:
>Hallo Michael,
>
>>
>> Sub ReadETBFile(ByVal sFilename As String) As String
>>
>> Dim ff As Integer, bChar As Byte
>> Dim iI As Integer, iY As Integer, iCountBlock As Integer, iZLen As
>> Integer
>> Dim iNextBlock As Integer
>> Dim sRufnr() As String, sBezeichnung1() As String, sBezeichnung2()
>> As String
>> Const kStartBlock = 217
>> Const kBlock = 204
>>
>> ff = FreeFile()
>> Open sFilename For Binary Access Read As #ff
>> iCountBlock = 0 'Zähler für 3er Blöcke initialisieren
>> iNextBlock = kStartBlock 'auf ersten Block setzen
>> iI = 1 'Array-Zähler initialisieren
>> Do While Not EOF(ff)
>> Seek #ff, iNextBlock 'Position für Leseoperation setzen
>> Get #ff, , bChar 'Hole Byte
>> If Hex(bChar) = 22 Then 'Eintrag vorhanden
>
>Warum fragst Du hier nicht einfach
>
> if bChar = &h22
>
>oder
>
> if bChar = 34
>
>Das würde dir die Umwandlung von bChar (Datentyp Byte) in einen String
>(Hex$()) ersparen.
Alles klar. Kannte das Kürzel für Hex nicht. Danke.
>
>
>
>> ReDim Preserve sRufnr(iI) 'Rufnummer
>> ReDim Preserve sBezeichnung1(iI) 'Nachname
>> ReDim Preserve sBezeichnung2(iI) 'Vorname
>> Seek #ff, iNextBlock + 10 'Position auf Rufnummerneintrag
>> Get #ff, , bChar 'Hole Byte (Erste Position ist Längenangabe)
>> iY = (bChar \ 2) + (bChar Mod 2) 'Länge gibt Nibbles an, also
>> Zähler umrechnen
>
>Warum nicht einfach iY = bChar\2 ?
Nun das ist einfach erklärt. Wenn Du einfach durch 2 teilst ohne Rest
und die Länge ist ungerade, dann liest die Funktion ein Byte zu wenig
ein. Deswegen muss mit 'Mod 2' der Rest ermittelt werden. Entspricht
somit ein Byte mehr.
>
>> For iZLen = 1 To iY 'Hole Rufnummer
>> Get #ff, , bChar
>> sRufnr(iI) = sRufnr(iI) & CStr(Hex(bChar))
>
>Wozu soll das CStr(Hex(bChar)) gut sein?
Das war ein Test. Ich weiß, dass das auch ohne CStr funzt.
>
>bChar ist ein Wert vom Typ Byte. Also ein numerischer Datentyp.
>Hex$(bChar) gibt einen String zurück, der den in bChar gespeicherten Wert in
>hexadezimaler Schreibweise darstellt.
>Ein nochmaliges cStr() ist hölzernes Holz.
>
>> Next iZLen
>> Get #ff, , bChar 'Hole nächstes Byte, wieder Längenangabe
>> If Hex(bChar) <> 0 Then 'Name vorhanden
>
>Hier wandelst Du den Inhalt von bChar (Datentyp Byte) in einen String um und
>vergleichst diesen String dann mit dem Wert 0, der den Typ Integer hat.
>Wenn bChar den Wert 0 enthält, dann gibt Hex$(bChar) einen Wert vom Typ
>Variant mit dem Untertyp String zurück, der das Zeichen "0" enthält.
>
>Datentypen sind offenbar nicht wirklich Dein Lieblingsthema.
Tja, wie gesagt, die gesamte Sub war noch nicht fertig. So fange ich
immer an zu programmieren. Anschliessend wird bereinigt.
>
>
>> iY = bChar 'Länge in Zähler
>> For iZLen = 1 To iY 'Hole Name
>> Get #ff, , bChar
>> sBezeichnung1(iI) = sBezeichnung1(iI) & Chr(CLng(bChar))
>
>Warum wandelst Du den Inhalt von bChar (Typ Byte) erst in einen Wert vom Typ
>Long (cLng) um?
>
> Dim byteValue as Byte
> byteValue = 57
>
> Debug.print Chr$(byteValue) -->> "9"
>
> Debug.print Chr$(cLng(bytValue)) -->> "9"
Aha! Interessant. Ich hatte das gemacht, weil die Chr Funktion einen
Wert vom Typ Long erwartet. Aber hier sieht man doch, daß man nie
auslernt. Besten Dank für den Hinweis.
>
>> Next iZLen
>> End If
>> Get #ff, , bChar 'Hole nächstes Byte
>> If Hex(bChar) <> 0 Then 'weiterer Name vorhanden
>
>Hier wieder diese völlig überflüssige Umwandlung eines Wertes vom Typ Byte
>in einen String mit der Funktion Hex(). Wozu soll das gut sein?
>
>
>> iY = bChar 'Länge in Zähler
>> For iZLen = 1 To iY 'Hole weiteren Namen
>> Get #ff, , bChar
>> sBezeichnung2(iI) = sBezeichnung2(iI) & Chr(CLng(bChar))
>
>Auch hier wieder diese völlig überflüssige Umwandlung des Wertes vom Typ
>Byte nach Typ Long.
>
>> Next iZLen
>> iNextBlock = Loc(ff) + 4 'Setze Position auf nächsten Eintrag
>> Else
>> iNextBlock = Loc(ff) + 5 'Setze Position auf nächsten Eintrag
>> End If
>> iI = iI + 1 'Arrayzähler erhöhen
>> Else 'Kein weiterer Eintrag
>> MsgBox "Keine weiteren Einträge vorhanden!", vbOKOnly, "Ende"
>> Exit Do 'Verlasse Schleife
>> End If
>> If iI Mod 3 = 1 Then '3er Block abgearbeitet
>> iCountBlock = iCountBlock + 1
>> iNextBlock = kStartBlock + kBlock * iCountBlock 'auf nächsten
>> Block setzen
>> End If
>>
>> Loop 'Ende des Files nicht erreicht, weiter
>>
>> Close #ff 'Schliesse File
>>
>> End Sub
>>
>> Hier nochmals kurz das Format im Klartext:
>> Die ersten 216 Byte beinhalten Zusatzinformationen.
>> Position 217 = Kennbyte, Hex 22 = Eintrag vorhanden
>
>Es ist also ein Eintrag vorhanden, wenn das Byte den Wert 34 (&h22)
>enthält.
Exakt.
>
>
>> Position 217 + 10 = Längenangabe gespeicherte Rufnummer
>> Die Rufnummer ist im Klartext in den Hexwerten vorhanden und zwar so,
>
>Klartext in Hexwerten?
>Es verstärkt sich mehr und mehr der Eindruck, dass Dir der Unterschied
>zwischen Strings, sowie numerischen Ganzzahldatentypen deren Werte man
>sowohl im dezimalen als auch im hexadezimalen Zahlensystem darstellen kann,
>absolut unklar ist.
Das denke ich nicht, Peter. Wenn ich die Zahl 66 in Hex umwandle,
kommt bei mir immer noch 42 heraus. In ASCII übersetzt entspricht dies
'B'
Man hätte das Ganze nämlich auch so kodieren können:
Länge = &h04
Rufnummer = &h06 &h06 &h02 &h01
oder
Rufnummer = &h36 &h36 &h32 &h31
oder
Rufnummer = &h42 &h15
>
>> 1. Beispiel: 04 66 21
>
>Du liest hier also 3 Bytes mit den Werten
>
> &h04, &h66, &h21
>
>ein?
Richtig.
>
>
>> Länge 4
>> Rufnummer = 6621
>> 2. Beispiel 0D 00 52 51 69 36 68 7F
>
>und hier die Bytefolge
>
> &h0D, &h00, &h52, &h51, &h69, &h36, &h69, &h7F
>
>> Länge D = 13
>> Rufnummer = 0 (<--Amtsholung) 05251 6936687
>
>> Das letzte Nibble ist nur zum Füllen und ist immer F
>
>Dum meinst das letzte HalbByte.
Halbbyte = Nibble
Nibble = Halbbyte
Also Peter, ich bitte Dich, das solltest gerade Du doch wissen.
>
>> Hinter der Rufnummer kommt wieder ein Byte mit einer Längenangabe
>> z.B. 06 und dann 6 Byte in ASCII für Name, anschliessend optional
>> wieder eine Längenangabe und die entsprechenden Bytes ASCII für eine
>> weitere Bezeichnung. Abschluss sind 4 Füllbytes.
>>
>> Das Problem:
>>
>> Wenn die Rufnummer ausgelesen wird, holt die Funktion GET das Byte
>> immer als Dezimal.
>
>Falsch,
Nein, richtig. Probier es selbst aus mit Debug.Print
Get holt ein Byte als dezimalen Wert!
>Get liest ein Byte, dieses hat den Datentyp Byte. Das hat absolut nichts mit
>Dezimal oder Hexadezimal oder sonst irgendeinem Zahlensystem zu tun.
Dem stimme ich nicht zu. Rechner speichern Daten in hexadezimaler
Notation, also Basis 16.
Ich könnte Dir jetzt auch erklären warum das so ist, das würde
allerdings den Rahmen dieser Diskussion sprengen.
>Du kannst die Zahlenwert 57 in dezimaler Schreibweise mit eben "57"
>darstellen aber genausogut in hexadezimaler Schreibweise als "39" und wenn
>es binär dargestellt sein soll, dann sieht das eben so aus "00111001".
>
> dim byteWert as Byte
>
> byteWert = 57
>
>ist exakt dasselbe wie
>
> byteWert = &h39
>
>> Ist der Inhalt Hex 00, bekomme ich 0
>
>Logisch, weil &h00 nicht anderes als 0 ist.
>Bei den (dez.) Zahlenwerten im Bereich 0 bis 9 gibt es keinen Unterschied in
>der Darstellungsweise gegenüber der hexadezimalen Schreibweise:
>
>dez hex
> 0 0
> 1 1
> 2 2
> 3 3
> 4 4
> 5 5
> 6 6
> 7 7
> 8 8
> 9 9
>10 A
>11 B
>12 C
>13 D
>14 E
>15 F
100 Punkte. Absolut richtig.
>
>
>> Ich brauche aber unbedingt beide Nullen.
>> Wie stelle ich das an?
>
>Erst mal begreifen, dass ein numerischer Datentyp wie z.B. Byte, Integer
>oder Long was ganz anderes ist als ein String in dem eine Zahl in dezimaler
>oder hexadezimaler Schreibweise abgebildet wird.
Das habe ich.
>
>
> dim byteValue as Byte
> dim strValue as String
>
> byteVale = 123
> strValue = replace(format$(hex$(byteVAlue), "@@"), " ","0")
> Debug.Print strValue -->> 7B
>
> byteValue = 5
> strValue = replace(format$(hex$(byteValue), "@@"), " ","0")
> Debug.print strValue -->> 05
>
Die unten stehende Erklärung, hättest Du nicht extra anführen müssen.
Ich habe das schon richtig verstanden.
Also ist nach soviel BlaBla der obige Code die Lösung bzw. Antwort auf
meine Anfrage?
Jedoch funzt es mit meiner Lösung auch sehr gut.
>Die Funktion hex$() macht aus dem an sie übergebenen Wert (byteValue) einen
>String, welcher eine Darstellung der in bytValue enthaltenen Zahl in
>hexadezimaler Schreibweise enthält.
>
>Format$(hex$(byteValue), "@@") formatiert den von hex$() zurückgegebenen
>String so, dass er bei Bedarf mit einem führenden Leerzeichen auf 2 Stellen
>aufgefüllt wird.
>
>Mit Replace(Format$(Hex$(byteValue), "@@"), " ", "0")
>wird das von Format$() zum Auffüllen verwendete Leerzeichen durch das
>Zeichen "0" erstetzt.
>
>
>> Nun bin ich ganz Ohr oder besser Auge..;-)
>
>Ich würde Dir dringend empfehlen, Dich mal mit dem Thema Datentypen zu
>befassen und hier ganz besonders den Unterschied zwischen
>Zahlendarstellungen in Strings (egal ob dezimal oder hexadezimal) und
>tatsächlichen Zahlen in numerischen Datentypen wie z.B. Byte, Integer oder
>Long herauszuarbeiten.
Keine Bange. Das brauche ich nicht mehr.
Allerdings würde ich Dir mal empfehlen nach der Bedeutung des Wortes
Nibble zu googeln. Ergibt 9930 Treffer.
Ebenfalls würde ich empfehlen, dass Du Dir mal binäre Dateien mit
einem Hexeditor anschaust (warum dieser wohl Hexeditor heisst...) oder
mal ein Programm disassemblierst. Du wirst schnell den Unterschied
zwischen Text und binär erkennen.
>Du würfelst in Deinem Code alles kunterbunt durcheinander. Bei Deinem Code
>hat VB mehr damit zu tun, per automatischer Typumwandlung jeweils Deine
>unpassenden Datentypen in passende umzuwandeln, als mit der eigentlichen
>Abarbeitung Deines Codes.
Ich kann hier lediglich nochmals betonen, das der obige Code der erste
geistige Erguss war, der natürlich anschliessend bereinigt wird und
bereits wurde. Ebenfalls teste ich einige Sachen darin.
Bei einem Problem mache ich mir nämlich nicht erst einen Plan und
programmiere dann, sondern fange einfach an. Das mag den Einen oder
Anderen hier entrüsten, jedoch ist das für mich ein gangbarer Weg.
Mittlerweile ist das Proggie bereinigt und läuft.
>
>Damit kannst Du z.B. die gesamte Bytefolge bis zum EOF in einen String
>einlesen, welcher die einzelnen Bytewerte in hexadezimaler Schreibweise
>abbildet:
>
> Dim bBuffer As Byte
> Dim intFN As Integer
> Dim strBuffer As String
>
> intFN = FreeFile
> Open "D:\Testdatei.txt" For Binary Access Read As #fn
> Do Until EOF(intFN)
> Get #1, , bBuffer
> strBuffer = strBuffer & _
> Replace(Format$(Hex$(bBuffer), "@@"), " ", "0")
> Loop
> Close intFN
Vielen Dank. Aber mit dem obigen Code habe ich dann genau dasselbe wie
vorher. Ich lese eine binäre Datei ein und bekomme eine binäre Datei.
Wie soll das mein Problem lösen?
Peter sagt: "Ich habe für Dich eine Lösung!"
Michael sagt: "Aber die passt irgendwie nicht zum Problem."
>
>Gruß aus St.Georgen
>Peter Götz
>www.gssg.de (mit VB-Tips u. Beispielprogrammen)
>
Grüsse aus Paderborn / NRW
Michael Windmeier
Systemspezialist Telekommunikationstechnik
- Next message: Dieter Strassner: "Re: Error 1053 bei Start eines Service mit NTSVC.OCX"
- Previous message: Jens Duczmal: "Re: 2 Bilder vergleichen"
- In reply to: Peter Götz: "Re: Datei binär einlesen"
- Next in thread: Michael Windmeier: "Re: Datei binär einlesen"
- Reply: Michael Windmeier: "Re: Datei binär einlesen"
- Reply: Peter Götz: "Re: Datei binär einlesen"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|