vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Mails senden, abrufen und decodieren - ganz easy ;-)  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Fortgeschrittene
Einlesen von Datenstrukturen aus einer Datei (erzeugt mit einer anderen Sprache) 
Autor: Schudi
Datum: 19.11.18 16:09

Es geht darum strukturierte Daten aus einer Datei auszulesen, die mit einer anderen Programmiersprache (in diesem Fall MF Cobol) erstellt wurde.

Ich kann die Daten satzweise (die Satzlänge und der interne Satzaufbau sind bekannt) per StreamReader einlesen, so dass ich in der Variablen "Datensatz", definiert als String, jeweils einen Datensatz erhalte. Wie teile ich diesen aber nun auf die einzelnen Felder auf?

In der ursprünglichen Struktur besteht der Datensatz natürlich aus Datenfeldern. In Cobol sieht das beispielsweise so aus:

02 PFAmc pic x(10)
02 PFAnum pic 999 comp-6.
02 PFAbez pic x(30).
02 PFAvki pic s9(5)v99 comp-5.


Pic x entspricht einem String - in diesem Fall von 10 Byte Länge. Hier könnte ich natürlich einfach Byte 1-10 bzw. entsprechend der Position (für PFAbez also Byte 13 - 42) des eingelesenen Strings "Datensatz" ablegen. Kein Thema - wenn auch vielleicht nicht elegant.

Pic 999 Comp-6 entspricht einem numerisch gepacktem Datenfeld von 2 Byte Länge. Inter dargestellt im "packed decimal format"

s9(5)v99 comp-5 entspricht einem numeroisch gepacktem Datenfeld von 4 Byte Länge mit Vorzeichen.

Eine Beschreibung der Formate aus MF Cobol findet sich hier:

https://documentation.microfocus.com/help/index.jsp?topic=%2FGUID-0E0191D8-C39A-44D1-BA4C-D67107BAF784%2FBKCGCGRMDFS003.html

Wie bekomme ich die Feld bzw. den Datensatz nun korrekt in eine VB-Structure oder Klasse? Muss ich wirklich jedes Feld einzeln behandeln?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Einlesen von Datenstrukturen aus einer Datei (erzeugt mit einer anderen Sprache) 
Autor: Manfred X
Datum: 20.11.18 09:12

Hallo!

Schau mal hier ....
https://www.c-sharpcorner.com/article/cobol-and-net-data-types/

https://community.microfocus.com/microfocus/cobol/net_express__server_express/w/knowledge_base/2433/mapping-data-types-between-cobol-with-c

Beitrag wurde zuletzt am 20.11.18 um 09:21:42 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Einlesen von Datenstrukturen aus einer Datei (erzeugt mit einer anderen Sprache) 
Autor: Schudi
Datum: 20.11.18 12:16

Hallo Manfred X,

und erst einmal vielen Dank für Deine Antwort.

Insbesondere der 2. Artikel war mir bekannt, aber es geht hier nicht um die Übergabe als Parameter sondern um einen String, der aus einer Datei gelesen wird.

Ich konkretisiere meine Anfrage mal ein wenig...

Als Beispiel nehme ich die Struktur aus meinem gestrigen Post...

Im Cobol sieht die Beschreibung so aus:

02 PFAmc pic x(10) Wert Klartext: ABCDEFGHIJ Wert hex: 41 42 43 44 45 46 47 48 49 4A
02 PFAnum pic 999 comp-6. Wert Klartext: 115 Wert hex: 01 15
02 PFAbez pic x(10). Wert Klartext: Text Wert hex: 54 65 74 78 20 20 20 20 20 20
02 PFAvki pic s9(5)v99 comp-5. Wert Klartext: 0,08 Wert hex: 08 00 00 00
02 PFAvoll Pic s9(8) comp-5. Wert Klartext: 33377- Wert hex: 9F 7D FF FF
02 PFAleer Pic s9(8) comp-5. Wert Klartext: 557 Wert hex: 2D 02 00 00

In der Datei, und somit in dem String, den ich aus der Datei einlese, sieht das so aus (in Hex):


Klartext:"ABCDEFGHIJ Text Ÿ}ÿÿŸ}ÿÿ" insgesamt 34 Byte

in hex:" 54 65 74 78 20 20 20 20 20 20 08 00 00 00 9F 7D FF FF 2D 02 00 00"


Ausgehend von dem ersten Dokument müsste das folgender Structure entsprechen:

Structure Artikel
     Dim Mc As String
     Dim Num As Integer
     Dim Bez As String
     Dim Vki As Integer
     Dim AnzVol As Integer
     Dim AnzLer As Integer
End Structure
Da VB.net keine String-Variablen mit fester Länge kennt, muss ich doch alle "Felder" einzeln aus dem String ausschneiden und in die Zielfelder übertragen, oder?

Für die Textfelder ist das noch recht einfach:

Public Sub SatzZerlegen(SatzGelesen As String)
 
       Dim myArtikel As New Artikel
 
       'Zuerst die Textfelder
       myArtikel.Mc = Mid(SatzGelesen, 1, 10)
       myArtikel.Bez = Mid(SatzGelesen, 15, 10)
 
End Sub
Aber jetzt kommen die numerischen Felder:

Die Definition S9(8) Comp-5 (4 Byte) entspricht einer Int32. Soweit ist das klar.

In der Datei stellen sich die 4 Byte in Hex wie folgt dar: 08 00 00 00

Aber ich kann mir nicht vorstellen, dass der folgende Code schon ausreicht bzw. funktioniert...

       ...
       myArtikel.vki = CInt(Mid(SatzGelesen, 26, 4))
Und spätestens für die Comp-6 definierten Felder gibt es keine Entsprechung - auch in dem genannten Dokument nicht.

Nehmen wir die Nummer : 115 im Klartext

In der Datei stellen sich die 2 Byte in Hex wie folgt dar: "01 15"

Je Ziffer also ein Halbbyte und das Ganze rechtsbündig.

Wie bekomme ich das jetzt in eine Integer? Hier muss ich doch umrechnen, oder? Aber wie?

Oder anders ausgedrückt: Wie wird aus dem 2 Byte langen String hex "01 15" wieder die Zahl 115?


Ich entschuldige mich schon mal für den langen Text und meine umständliche Erklärung, aber vielleicht ist mein Problem jetzt deutlicher geworden...
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Einlesen von Datenstrukturen aus einer Datei (erzeugt mit einer anderen Sprache) 
Autor: Kuno60
Datum: 20.11.18 22:09

Hallo,

die Datei kannst du, zum Beispiel so, in deine Struktur einlesen:
Artikel kann auch eine Klasse sein.

  Structure Artikel
    Dim Mc As String '10 Byte
    Dim Num As Short '2 Byte
    Dim Bez As String '10 Byte
    Dim Vki As Integer '4 Byte
    Dim AnzVol As Integer '4 Byte
    Dim AnzLer As Integer '4 Byte
  End Structure
 
  Sub LeseDatei()
    Dim s = IO.File.OpenRead("Datei")
    Dim r = New IO.BinaryReader(s)
 
    'einen Satz lesen
    Dim a As New Artikel
    a.Mc = r.ReadChars(10)
    a.Num = BcdToInt16(r.ReadInt16)
    a.Bez = r.ReadChars(10)
    a.Vki = r.ReadInt32
    a.AnzVol = r.ReadInt32
    a.AnzLer = r.ReadInt32
 
    r.Close()
  End Sub
 
  'Binärcodierte Dezimalzahl, in Binärzahl umwandeln
  Function BcdToInt16(w As Short) As Short
    Dim rg As Short = 0
    For i = 0 To 3
      rg += ((w >> i * 4) And &HFS) * CShort(10 ^ i)
    Next
    Return rg
  End Function
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Einlesen von Datenstrukturen aus einer Datei (erzeugt mit einer anderen Sprache) 
Autor: effeff
Datum: 23.11.18 10:03

Schudi schrieb:
Zitat:

Da VB.net keine String-Variablen mit fester Länge kennt...


Siehe https://docs.microsoft.com/de-de/dotnet/api/microsoft.visualbasic.compatibility.vb6.fixedlengthstring.-ctor?view=netframework-4.7.2

EALA FREYA FRESENA

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Einlesen von Datenstrukturen aus einer Datei (erzeugt mit einer anderen Sprache) 
Autor: Schudi
Datum: 26.11.18 13:27

Vielen Dank, Kuno!

Das ist schon sehr, sehr dicht dran.

Aber aus hex"01 15" wird mit der Routine "1501" - also immer Paare zu 2 Ziffern (1 Byte im hex-String) genau umgekehrt....

Ich habe die Routine zusätzlich auf 4-Byte Variablen angepasst indem ich r.ReadInt32 verwende und short durch Integer getauscht habe, was auch klappt, aber auch hier:

    Function BcdToInt32(w As Integer) As Integer
        Dim rg As Integer = 0
        For i = 0 To 7
            rg += ((w >> i * 4) And &HFS) * CInt(10 ^ i)
        Next
        Return rg
    End Function
Aus hex"19 99 10 18" wird "18109919" - also immer Paare zu 2 Ziffern (1 Byte im hex-String) genau umgekehrt...

Bei der Konvertierung wird die Reihenfolge vertauscht. Die letzten beiden Ziffern 19 stehen am Anfang und die ersten beiden "18" am Ende. Alle Werte dazwischen sind entsprechend...

rg nimmt im Verlauf der Schleife folgende Werte an:

i=0 0
i=1 +1 = 1
i=2 +500 = 501
i=3 +1000 = 1501

Vielleicht bekommen wir das auch noch hin... Wäre super.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Einlesen von Datenstrukturen aus einer Datei (erzeugt mit einer anderen Sprache) 
Autor: Schudi
Datum: 26.11.18 14:38

Vielen Dank effeff,

ok, da war meine Annahme, dass VB.net keine String-Variablen mit fixer Länge kennt, wohl falsch.

Und wieder bin ich ein bisschen schlauer.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Einlesen von Datenstrukturen aus einer Datei (erzeugt mit einer anderen Sprache) 
Autor: Kuno60
Datum: 26.11.18 23:40

Hallo Schudi,

normalerweise kommt in Windows-Dateien immer das niederwertigste Byte zuerst. Das ist auch bei binärcodierten Dezimalzahlen so.
Mag sein, dass das bei Cobol anders ist.

Also in deinem Beispiel, müsstest du dann die Bytes vertauschen, damit das Ergebnis richtig ist.
  Function BcdToInt16(b() As Byte) As Short
    Array.Reverse(b)
    Dim w = BitConverter.ToInt16(b, 0)
    Dim rg As Short = 0
    For i = 0 To 3
      rg += ((w >> i * 4) And &HFS) * CShort(10 ^ i)
    Next
    Return rg
  End Function
 
  a.Num = BcdToInt16(r.ReadBytes(2))
oder als Integer (4 Byte):
  Function BcdToInt32(b() As Byte) As Integer
    Array.Reverse(b)
    Dim w = BitConverter.ToInt32(b, 0)
    Dim rg As Integer = 0
    For i = 0 To 7
      rg += ((w >> i * 4) And &HF) * CInt(10 ^ i)
    Next
    Return rg
  End Function
 
  a.Num = BcdToInt32(r.ReadBytes(4))
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Einlesen von Datenstrukturen aus einer Datei (erzeugt mit einer anderen Sprache) 
Autor: Schudi
Datum: 27.11.18 06:10

Ganz herzlichen Dank. Läuft!
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Sie sind nicht angemeldet!
Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel