Toon posts:

[VB.NET]Hoe vb6.get te gebruiken in VB.net

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

Verwijderd

Topicstarter
Ik ben bezig om een applicatie geschreven in VB6 om te zetten naar VB.NET. Deels omdat het dan als plug-in te gebruiken is in een ander programma, deels om VB.NET te leren.
Ik zit momenteel vast op het gedeelte waar ik een binaire bestand moet openen en vervolgens data eruit te halen en weg te schrijven naar een ASCII-bestand.
Het binaire bestand bestaat uit een header en data (in dit geval een gridbestand). Het uitlezen van de header gaat al goed alleen het lezen van de data nog niet. In VB6 deed ik dat door de data in een array te stoppen, maar ik kan de VB.NET versie niet vinden.
Hier is de VB6 code:
Visual Basic 6:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Dim nRows As Long
Dim nCols As Long
Dim lDataLength As Long
Dim xLL As Double, yLL As Double
Dim xSize As Double, ySize As Double, blankValue As Double

  lFileBinaryRead = FreeFile
  Open sTempname For Binary As #lFileBinaryRead
  
  'Overzicht staat op:
  'http://www.geospatialdesigns.com/surfer7_format.htm
'Lees de header:
  Get #lFileBinaryRead, 21, nRows
  Get #lFileBinaryRead, 25, nCols
  Get #lFileBinaryRead, 29, xLL
  Get #lFileBinaryRead, 37, yLL
  Get #lFileBinaryRead, 45, xSize
  Get #lFileBinaryRead, 53, ySize
  Get #lFileBinaryRead, 85, blankValue
  
  lDataLength = ((nRows * nCols) - 1)
  ReDim arr(lDataLength)
'Lees de data  
  Get #lFileBinaryRead, 101, arr
  
  'Bestand sluiten:
  Close #lFileBinaryRead


Dit is de code die ik in VB.NET gebruik:
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
            Dim fs As System.IO.FileStream = New System.IO.FileStream(sGridFilename, IO.FileMode.Open)
            Dim br As System.IO.BinaryReader = New System.IO.BinaryReader(fs)
            'Overview at http://www.geospatialdesigns.com/surfer7_format.htm
'Lees de header:
            br.ReadInt32() 'Tag: Id for Header section: 4 bytes
            br.ReadInt32() 'Tag: Size of Header section: 4 bytes
            br.ReadInt32() 'Header Section: Version: 4 bytes
            br.ReadInt32() 'Tag: ID indicating a grid section: 4 bytes
            br.ReadInt32() 'Tag: Length in bytes of the grid section: 4 bytes
            Dim nRows As Integer = br.ReadInt32() 'Grid Section: nRow: 4 bytes
            Dim nCols As Integer = br.ReadInt32() 'Grid Section: nCol: 4 bytes
            Dim xLL As Double = br.ReadDouble()  'Grid Section:  xLL: 8 bytes
            Dim yLL As Double = br.ReadDouble() 'Grid Section:  yLL: 8 bytes
            Dim xSize As Double = br.ReadDouble() 'Grid Section: xSize: 8 bytes
            Dim ySize As Double = br.ReadDouble() 'Grid Section: ySize: 8 bytes
            br.ReadDouble() 'Grid Section: zMin: 8 bytes
            br.ReadDouble() 'Grid Section: zMax: 8 bytes
            br.ReadDouble() 'Grid Section: Rotation: 8 bytes
            Dim BlankValue As Double = br.ReadDouble() 'Grid Section: BlankValue: 8 bytes
            br.ReadInt32() 'Tag: ID indicating a data section: 4 bytes
            br.ReadInt32() 'Tag: Length in bytes of the data section (5 rows x 10 columns x 8 bytes per double): 4 bytes
            'Read griddata:
            Dim DataLength As Integer = ((nRows * nCols) - 1)
            Dim griddata(DataLength) As Double
'Lees de data, hier kom ik niet uit:
            'br.Read( 'Grid data. First value is the lower left node, and the subsequent nodes procede across the row until the end, then up to the second row, etc., until finishing at the upper right node: 8 bytes

            'Close
            br.Close()


Graag advies hoe dit op te lossen.

  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Ik ga er even van uit dat de data bytes zijn waar je iets mee wil gaan doen?

Indien dat zo is, dan wordt je code het volgende:
Visual Basic .NET:
1
2
3
4
lDataLength = ((nRows * nCols) - 1)
Dim returnValue As Byte()

returnValue = br.ReadBytes(lDataLength)


Overigens is dit gewoon het raadplegen van de handleiding van microsoft:
http://msdn2.microsoft.co...binaryreader_members.aspx

Verwijderd

Topicstarter
@BigBeng; dank je wel voor de suggestie. Ik ben er gelijk mee aan de slag gegaan, maar nu krijg ik niet de juiste double waarden uit de bytes array.
Dit is mijn code:
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
            'Read griddata:
            Dim DataLength As Integer = ((nRows * nCols) - 1)
            Dim griddata() As Byte
            griddata = br.ReadBytes(DataLength) 'Grid data. First value is the lower left node, and the subsequent nodes procede across the row until the end, then up to the second row, etc., until finishing at the upper right node: 8 bytes

            'Write the data:
            'Read per row:
            Dim x, y As Integer
            For x = griddata.Length - nCols To 0 - nCols Step -1 * nCols
                'Read per column:
                Dim sRegel As String = ""
                For y = 1 To nCols
                    Dim dblTempValue As Double
                    Dim sCellWaarde As String
                    'x is start of the row:
                    Logger.Dbg("X: " & x & " Y: " & y)
                    dblTempValue = System.BitConverter.ToDouble(griddata, x + y)
                    Logger.Dbg("Byte: " & griddata(x + y) & " Double: " & dblTempValue)
                    If dblTempValue < BlankValue Then
                        sCellWaarde = Math.Round(dblTempValue, 4)
                    Else
                        sCellWaarde = cNoDataValue
                    End If
                    If sRegel = "" Then
                        sRegel = sCellWaarde
                    Else
                        sRegel = sRegel & vbTab & sCellWaarde
                    End If
                Next y
                'Hele rij, dus nu wegschrijven:
                oWrite.WriteLine(sRegel)
                MsgBox(sRegel)
                'Volgende rij
            Next x

Ik moet de data achterstevoren hebben, daarom begin ik onderaan en ga dan naar boven. De ASCII data moeten doubles zijn gescheiden door tabs en omdat het een grid is per regel een rij met alle kolomwaarden.
Dit is de vb6 code:
Visual Basic 6:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
  'De data:
  lMaxPoints = UBound(arr)
  lMinPoints = LBound(arr)
  'Van beneden naar boven lezen.
  'Start index nieuwe file:
  'Per row uitlezen:
  For x = lMaxPoints - nCols To lMinPoints - nCols Step -1 * nCols
    'Nu in de rij aan het begin beginnen en per kolom,
    'de waarde uitlezen:
    sRegel = ""
    For y = 1 To nCols
      'x is begin van de rij:
      dblTempValue = arr(x + y)
      If dblTempValue < blankValue Then
        sCellWaarde = Round(dblTempValue, 4)
      Else
        sCellWaarde = cNoDataValue
      End If
      If sRegel = "" Then
        sRegel = sCellWaarde
      Else
        sRegel = sRegel & vbTab & sCellWaarde
      End If
    Next y
    'Hele rij, dus nu wegschrijven:
    Print #lFileAppend, sRegel
  'Volgende rij
  Next x    


Graag nog een schopje in de goede richting _/-\o_

  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Nog eentje dan :)

Je geeft niet aan wat er fout aan is, maar kun je mij vertellen hoe de data er precies uitziet? Zijn het getallen in tekstueel formaat? Of zijn het echt binaire representaties van getallen?

Als het eerste het geval is, dan kun je beter regel voor regel als string inlezen en dan splitten op tabs en converteren, in het tweede geval, moet je weten of wat jij een double noemt, ook een .net double is. Hoeveel bytes in 1 double? Bij dotnet (aldus de bitconverter) is het 8 bytes voor een double. Zijn het in jouw bestandje 4 bytes, dan zul je ToSingle moeten gebruiken.

Verwijderd

Topicstarter
De binaire data staat in 8 bytes, dus ik kan ook in .NET double gebruiken, toch?
De header wordt wel goed gemaakt:
code:
1
2
3
4
5
6
7
NCOLS   157
NROWS   99
XLLCENTER   20465,90499
YLLCENTER   367322,4486
DX  3,497
DY  3,5097
NODATA_VALUE    -99

Hieronder had iets zoals dit moeten komen:
code:
1
2
3
4
-99  -99  -99  -99  -99  -99  -99  -99  -99  -99  -99  -99  -99  -99  -99  
-99  -99  -99  3.25  3.24  3.25  3.5  -99  -99  -99  -99  -99  -99  -99 -99
-99  -99  -99  3.25  3.25  3.35  3.4  -99  -99  -99  -99  -99  -99  -99 -99
etc.

Wat ik krijg bij regel 18: Logger.Dbg("Byte: " & griddata(x + y) & " Double: " & dblTempValue) is
Byte: 251 Double: 8,19059530015877E+54
Byte: 37 Double: -5,32747267687247E+290
Byte: 226 Double: -2,96433658630982E+107
Byte: 108 Double: 13,7011906845034
Etc.
De orde van grootte is helemaal mis, behalve de laatste in dit voorbeeld lijken de waarden er niet op.

En ik krijg ook nog een foutmelding:
code:
1
Destination array is not long enough to copy all the items in the collection. Check array index and length.

Op regel 17: dblTempValue = System.BitConverter.ToDouble(.gridData, x + y)
Deze fout treedt op in de eerste loop van x en als y 150 is.
Het lijkt erop dat de array griddata een verkeerd blok bytes heeft.
De griddata begint na 101 bytes en volgens mij begin ik dan ook met lezen.

Ik zie nu nadat ik bovenstaande heb ingetyped dat de double data een komma hebben ipv een punt, heeft dat er wat mee te maken? Ik ga dat in ieder geval aanpassen.

  • bigbeng
  • Registratie: Augustus 2000
  • Laatst online: 26-11-2021
Dit lijkt erop dat je de array index niet goed zet. Volgens mij zijn arrays in vb.net inmiddels ook zero-based, dus het kan zijn dat je de doorloop variabelen nog met een -1 moet bijstellen. Dit zou ook de rare getallen kunnen verklaren. Het wordt nu ff debuggen dus. Sowieso kan het handig zijn om even uit te schrijven hoe de array er naar jouw mening uit ziet en met welke stappen je er doorheen moet lopen.
Pagina: 1