Toon posts:

[VB6]Binair opslaan waarde met vaste grootte

Pagina: 1
Acties:
  • 454 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik heb een reeks getallen die varieren van 0 tot 200.
Deze getallen moeten in een binair bestand worden opgeslagen als een 'binary coded signed integer value'.
Voorbeeld:
(00000001)(00000004)(00000003)(00000006)..........
De haakjes zijn alleen geplaatst om het beter leebaar te maken.

De getallen moeten dus 8 lang zijn met voorloopnullen.
Ik heb het grootste gedeelte al klaar, alleen het correct wegschrijven van de getallen van 8 tekens lukt nog niet echt.
code:
1
2
3
4
5
6
7
Open sXmlGrdFile For Binary Access Write As #lFileGrdfile
For i = 0 To UBound(arr)
  sCellWaarde = arr(i)
  (...)
  Put #lFileGrdfile, LOF(lFileGrdfile), CInt(sCellWaarde)
Next i
Close #lFileGrdfile

Nu is mijn vraag waar ik nu precies de voorloopnullen moet maken. Is dat in de Put regel of moet ik niet een integer wegschrijven maar een string en daar de voorloopnullen in plaatsten.

Graag advies, want ik ben niet zo goed in binaire wegschrijven ;)

--
Paul

  • Tukk
  • Registratie: Januari 2002
  • Laatst online: 15-02 11:41

Tukk

De α-man met het ẞ-brein

Ten eerste, het 'getal' 00000004 is niet een binair getal, want 4 in binair is 100
Ten tweede zou ik de help file van VB eens goed doorlezen, bijvoorbeeld over de format-functie

http://www.apostate.com/programming/vb-format.html

Dit kun je dus meteen om de int in de put regel zetten, als je de waarden die wegschrijft ook
nog eerst wil controleren zou ik er even een kleine functie met foutafhandeling van maken.

edit:
Het Binary van de access slaat op de manier dat de wordt ingelezen, niet op het formaat van de data in de file.

[ Voor 47% gewijzigd door Tukk op 17-05-2006 14:07 ]

Q: How many geeks does it take to ruin a joke? A: You mean nerd, not geek. And not joke, but riddle. Proceed.


Verwijderd

Topicstarter
Je hebt helemaal gelijk, dat van Format had ik natuurlijk gewoon moeten weten ;)

Ik heb het aangepast, maar ik doe het nog niet helemaal goed. De waarde die ik moet wegschrijven moet 4 bytes groot zijn. En dat gaat niet goed met mijn huidige methode.

Ik heb in ieder geval mijn Put code aangepast:
code:
1
Put #lFileGrdfile, , Format(sCellWaarde, "00000000")

Mocht iemand zo weten hoe ik precies 4 bytes kan wegschrijven dan hoor ik het graag. ;)

Paul

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 13-02 20:06

Gerco

Professional Newbie

4 bytes en 8 karakters is niet mogelijk. Ik neem aan dat je je data wilt wegschijven zoals hij in het geheugen staat4, bytes, least significant byte first.

Dan kun je gewoon zo doen:
Visual Basic .NET:
1
2
3
4
5
Dim i As Long
i = 4567890
Open "file" For Binary Access Write As #1 Len=4
Put #1, ,i
Close #1


Als je iets anders bedoelt, zul je specifieker moeten zijn, want binary, 4 bytes en 8 karakters met voorloopnullen spreken elkaar nogal tegen. Er zijn ook nog verschillende manieren om een signed integer waarde te representeren in binaire data, welke van die bedoel je?

Ik heb het idee dat je niet precies weet wat je wilt doen.

[ Voor 17% gewijzigd door Gerco op 17-05-2006 15:24 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Verwijderd

Topicstarter
Ik heb het idee dat je niet precies weet wat je wilt doen.
Daar heb je helemaal gelijk in ;)

Ik heb een ISO-document waar in beschreven staat hoe het binaire bestand geschreven moet worden. Het bestand is nl. een inputfile voor het aansturen van een werktuig.

Het is een redelijk nieuwe standaard (isoBUS) en er is nog niet veel ervaring met het schrijven van de inputfiles in het algemeen en het schrijven van het binaire gedeelte in het bijzonder.

De inputfile is een XML-bestand, met een header, footer en data. Die data kan erg veel worden en daarom kan de data ook als een extern binair bestand worden meegeleverd.

Er is binnen Nederland 1 iemand die er meer verstand van heeft en hij heeft ook zo'n boordcomputer waarmee hij de data kan controleren. Naar hem stuur ik mijn data ter controle en na een dag of wat krijg ik terug of het goed is of niet.
Technisch weet hij ook niet precies hoe het moet en dan maakt mij erg eenzaam ;(

Ik heb wel voorbeelden van de inhoud van het binaire bestand:
(00000001)(00000004)(00000003)(00000006)..........
De haakjes zijn alleen geplaatst om het beter leebaar te maken.

Dit voorbeeld geeft 4 waarden aan nl. 1 4 3 en 6
Hier komt mijn idee van de 8 karakters en voorloopnullen vandaan.
Nu blijkt dat het hier om hex getallen gaat van 4 bytes.
De oplossing van Gerco lijkt voor mijn toepassing niet geschikt omdat ik veel data moet wegschrijven en de Put regel zit dan ook in een Loop. Zie mijn voorbeeld in mijn startpost.

Als iemand nog suggesties heeft dan graag, want ik ben al de hele week aan het zoeken en lezen en ik kom nog niet echt verder.

Paul

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 21:04

Creepy

Tactical Espionage Splatterer

Binaire bestand? Ik zie gewoon een tekst bestand met voorloop nullen. Lijkt me dat het vrij eenvoudig is om het aantal karakters van een string te tellen en er vervolgens genoeg voorloop nullen voor plaatsen zodat dit lang genoeg is.

Maar aangezien je het over 4 bytes per getal hebt, kan het zijn dat je BCD notatie wilt hebben (als je bits i.p.v. bytes bedoelt tenminste :P )? Kijk dan ook eens hier http://hyperphysics.phy-a...e/electronic/number2.html en hier: http://hyperphysics.phy-a...lectronic/number3.html#c1

Let er wel op dat als je zo'n bestand opent in bijv. een text editor je vaak een hex notatie ziet (getallen van 0-255). Dit is niet hetzelfde als een tekst bestand met hierin de getallen ;)

[ Voor 12% gewijzigd door Creepy op 17-05-2006 16:36 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 13-02 20:06

Gerco

Professional Newbie

Ik denk dat je dat voorbeeld anders moet lezen. Die cijfers zijn geen ascii karakters, maar gewoon bytes. Dit kun je hexadecimaal als volgt representeren:

00 00 00 01 00 00 00 04 00 00 00 03 00 00 00 0616

Hierbij stelt steeds een groepje van twee hexadecimale cijfers 1 byte voor. In dit bestand staan dus 16 bytes. Dit lijkt een most significant byte first notatie te zijn en die bereik je helaas niet door een Integer of Long zo in een bestand te PUT'en (dat is namelijk de least significant byte first).

Je zou zoiets kunnen doen:
Visual Basic .NET:
1
2
3
4
5
6
Public Sub PUTLong(FileHandle As Integer, Value As Long)
  Put #FileHandle, , (Value And &HFF000000)
  Put #FileHandle, , (Value And &H00FF0000)
  Put #FileHandle, , (Value And &H0000FF00)
  Put #FileHandle, , (Value And &H000000FF)
End Sub


Dit zet past een bitmasker toe op de waarde in het geheugen om de goede byte eruit te krijgen. Als je namelijk gewoon "Put #1, , Value" had gedaan, zou er dit uitkomen:

01 00 00 0016

en dat zou in jouw bestand het decimale getal 1677721610 betekenen en niet 110.

[edit]
Creepy zou ook heel goed gelijk kunnen hebben met zijn BCD notatie. Lees daar je documentatie goed op na. Er kan niet gewoon "binaire representatie" staan, aangezien dat bijna niets zegt. ASCII karakters in een bestand is ook een binaire representatie.

[edit2]
1016 betekent "het hexadecimale getal 10", wat gelijk is aan het decimale getal 16, oftwel 1610.

[ Voor 33% gewijzigd door Gerco op 17-05-2006 16:45 ]

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Verwijderd

Topicstarter
Het ziet er allemaal ingewikkeld uit, ik zal daar morgen eens goed naar kijken.
Alvast erg bedankt.

Paul

Verwijderd

Topicstarter
Het is al weer even geleden, maar ik ben er weer mee bezig en ik weet wat meer.
Ik moet 8 bits Bytes wegschrijven.

Als ik het via de PutLong functie gebruik van Gerco krijg ik een veel te groot bestand en dat bestand is ook niet goed.

Als ik het met de volgende code doe, krijg ik 16 bits words:
code:
1
2
3
4
5
6
7
8
9
10
11
  'format de data:
  For i = 0 To UBound(arr)
    dTempValue = arr(i)
    If dTempValue < blankValue Then
      iCellWaarde = Int(dTempValue * dScale)
    Else
      iCellWaarde = cNoDataValue
    End If
    Put #lFileGrdfile, , iCellWaarde
    'Call putLong(lFileGrdfile, iCellWaarde)
  Next i

arr() is een array met de waarden in doubles, dScale is de eventuele schaal is in dit voorbeeld 1.0
De waarde die in het binaire bestand moet komen is een heel getal, vandaar de Int().

Ik krijg nu 16 bits words. Ik ben er dus bijna ik moet dus voor iedere cell 1 byte wegschrijven ipv 2 bytes.

Maar hoe doe ik dat??
Heeft iemand een idee?

Alvast bedankt.

Paul

  • MuggenHor
  • Registratie: Juli 2003
  • Laatst online: 26-01-2025
Ok, dus als ik het goed begrijp liggen alle waarden in de array arr() tussen de 0 en 200 en wil je elk van de waarden in deze array wegschrijven als een byte (btw "8 bits Bytes"? bytes zijn de afgelopen 40 jaar geloof ik altijd 8 bit lang geweest maar ok).

0 =< iCellWaarde => 200 (aanname)

Hmm, nu ik er zo naar kijk lijkt het vrij simpel te zijn. Probeer iCellWaarde eens zo te declareren:
code:
1
Dim iCellWaarde As Byte


Zolang (0 =< iCellWaarde => 255) = True zou dit moeten werken zonder fouten (Je zou de Int() ook kunnen laten vallen: weer een functie minder weer 14 clockcycles per loop minder :) ).

Waarheid is pas waarheid als het tegendeel ook waarheid is.


  • Henk007
  • Registratie: December 2003
  • Laatst online: 06-04-2025
laat maar

[ Voor 88% gewijzigd door Henk007 op 21-07-2006 14:49 ]


Verwijderd

Topicstarter
Als ik het zo lees, lijkt het me erg logisch.

Ik heb een nieuwe versie gemaakt van mijn bestand en die is ook de helft kleiner dan het bestand wat uit 16 bits words bestaat, dus het lijkt goed te gaan.
Ik stuur de bestanden op en dan hoor ik vandaag of maandag wel of het nu goed is.

Ik ga in ieder geval met een goed gevoel het weekend in.

Bedankt voor alle hulp. _/-\o_

--
Paul

Verwijderd

Dit klinkt wel heel erg 'trial and error'...
'binary coded signed integer value' betekent gewoon een (meestal) 32 bits reeks waarbij de 1e bit bepaalt of 't + of - is (0=positief, 1=negatief), en de overige 31 bits de waarde aangeven. In jouw geval heb je alleen positieve getallen, dus die 1e bit kun je vergeten (= gewoon 0 laten).

Gerco's oplossing met die masks komt dan het best in de buurt, hij converteerde de signed integer naar 4 bytes, althans dat probeerde hij.
Alleen vergat 'ie 2 belangrijke dingen:

- bij de 4 'put' commando's schreef 'ie steeds 4 bytes weg (32 bits i.p.v. 8), en
- als 'ie al het idee had dat 'ie 1 byte schreef, vergat 'ie dat je dan bij 't 1e 24 bits naar rechts moet shiften, bij 't 2e 16, en bij 't 3e 8. De meeste talen die bitwise operators ondersteunen hebben daar een 'shr' operator voor (op C na, daar heet 't '>>'). Ik neem aan dat VB6 dat ook heeft?

Zo ja, dan gaat Gerco's code er iets als dit uitzien (beschouw 't als pseudo-code, ik heb nog nooit iets met VB6 gedaan):
Visual Basic:
1
2
3
4
5
6
7
8
9
10
11
Public Sub PUTLong(FileHandle As Integer, Value As Long) 
  Dim bt as Byte
  bt = (Value And &HFF000000) Shr 24
  Put #FileHandle, , bt
  bt = (Value And &H00FF0000) Shr 16
  Put #FileHandle, , bt
  bt = (Value And &H0000FF00) Shr 8
  Put #FileHandle, , bt
  bt = (Value And &H000000FF)
  Put #FileHandle, , bt
End Sub

[ Voor 7% gewijzigd door Verwijderd op 21-07-2006 22:11 ]


Verwijderd

MuggenHor schreef op vrijdag 21 juli 2006 @ 14:44:
Ok, dus als ik het goed begrijp liggen alle waarden in de array arr() tussen de 0 en 200 en wil je elk van de waarden in deze array wegschrijven als een byte
Dan heb je 't denk ik niet goed begrepen: TS moet die waarde aanleveren als 'binary coded signed integer value'. Oftewel 1 sign bit en 31 bits die de waarde aangeven.
Hmm, nu ik er zo naar kijk lijkt het vrij simpel te zijn. Probeer iCellWaarde eens zo te declareren:
code:
1
Dim iCellWaarde As Byte
Als 'de andere kant' een signed integer (4 bytes) verwacht, en je kiepert 1 byte in die file/stream/whatever, dan maak je geen vrienden.

pmeems, sorry dat ik je weekend vergal... :)

[ Voor 6% gewijzigd door Verwijderd op 21-07-2006 23:47 ]


Verwijderd

Topicstarter
@Afterlife: mijn weekend vergal je niet zo snel. Zeker niet als ik het er na pas lees ;)

Inderdaad is het 'trail and error' Dat heb je met nieuwe zaken :P Niet alleen is het nieuw voor mij, maar de inkt van het protocol is nauwelijks droog.

In ieder geval was de oplossing van MuggenHor de juiste. De waarde declareren als Byte is de truuk. Het heet niets voor niets visual Basic >:)

Erg bedankt voor het meedenken allemaal.

--
Paul

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 15-02 09:21

Janoz

Moderator Devschuur®

!litemod

Ik ben trouwens erg benieuwd hoe volgens die documentatie signed bytes groter dan 127 weggeschreven gaan worden.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'

Pagina: 1