| |
VB.NET - FortgeschritteneEinlesen 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? | |
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... | |
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 | |
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. | |
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. | |
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)) | |
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! | |
| 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 |
|
|
sevGraph (VB/VBA)
Grafische Auswertungen
Präsentieren Sie Ihre Daten mit wenig Aufwand in grafischer Form. sevGraph unterstützt hierbei Balken-, Linien- und Stapel-Diagramme (Stacked Bars), sowie 2D- und 3D-Tortendiagramme und arbeitet vollständig datenbankunabhängig! Weitere InfosTipp des Monats TOP Entwickler-Paket
TOP-Preis!!
Mit der Developer CD erhalten Sie insgesamt 24 Entwickler- komponenten und Windows-DLLs. Die Einzelkomponenten haben einen Gesamtwert von 1605.50 EUR...
Jetzt nur 599,00 EURWeitere Infos
|