Domanda

Sto usando implementazione EBCDIC di Jon Skeet in .NET per leggere un file VSAM scaricato in modo binario con FTP da un sistema mainframe. Funziona molto bene per la lettura / scrittura in questa codifica, ma non ha nulla a leggere i valori imballato-decimali. Il mio file contiene questi, e ho bisogno di decomprimere loro (a costo di più byte, ovviamente).

Come posso fare questo?

I miei campi sono definiti come PIC S9(7)V99 COMP-3.

È stato utile?

Soluzione

Ahh, BCD. Honk se è stato utilizzato nel 6502 assemblaggio.

Naturalmente, la cosa migliore è lasciare che lo SPOSTA COBOL fare il lavoro per voi! Una di queste possibilità può aiutare.

(Possibilità # 1) Supponendo che si ha accesso al mainframe e il codice sorgente, e il file di output è solo per il vostro uso, modificare il programma in modo che si muove solo il valore di una pianura spacchettato PIC S9 (7) V99 .

(Possibilità # 2) Supponendo che non è così (ingresso ad esempio, il file è per altri PGM, o non può cambiare il codice) è facile, è possibile scrivere un altro programma COBOL sul sistema che legge il file e scrive un altro. Tagliare e incollare il tracciato record file con il BCD nel nuovo programma per i file di input e di output. Modificare la versione uscita per essere non imballato. Leggere un record, fare un 'spostare' corrispondente per trasferire i dati, e scrivere, fino EOF. Poi il trasferimento che file.

(Possibilità # 3) Se non si può toccare il mainframe, notare la descrizione in questo articolo si è collegato nel tuo commento. BCD è relativamente semplice. E ' potrebbe essere facile come questo (vb.net):

Private Function FromBCD(ByVal BCD As String, ByVal intsz As Integer, ByVal decsz As Integer) As Decimal
    Dim PicLen As Integer = intsz + decsz
    Dim result As Decimal = 0
    Dim val As Integer = Asc(Mid(BCD, 1, 1))
    Do While PicLen > 0
        result *= 10D
        result += val \ 16
        PicLen -= 1
        If PicLen > 0 Then
            result *= 10D
            result += val Mod 16
            PicLen -= 1
            BCD = Mid(BCD, 2)
        End If
        val = Asc(Mid(BCD, 1, 1))
    Loop
    If val Mod 16 = &HD& Then
        result = -result
    End If
    Return result / CDec(10 ^ decsz)
End Function

L'ho provato con un paio di varianti di questa chiamata:

MsgBox(FromBCD("@" & Chr(13 + 16), 2, 1))

per es., È -40,1. Ma solo alcuni. Quindi potrebbe ancora essere sbagliato.

E allora se il comp-3 inizia, diciamo, dal byte 10 del tracciato record in ingresso, questo risolverebbe esso:

dim valu as Decimal = FromBCD(Mid(InputLine,10,5), 7,2))

Notando le formule da questo articolo i dati di conversione per il # di byte da inviare, e la # 9 di prima e dopo la V.

Il risultato viene memorizzato in un decimale per evitare errori di arrotondamento. Specialmente se si tratta di $$$. Float & Doppia causerà dolore! Se non sei elaborazione, anche una stringa è migliore.

, naturalmente, potrebbe essere più difficile. Dove lavoro, il mainframe è di 9 bit per byte. Grave. Questo è ciò che rende le prime 2 possibilità in modo saliente. Naturalmente ciò che rende meglio è il fatto che la si può essere un PC programmatore solo e questo è un grande scusa per avere un programmatore di mainframe per fare il lavoro per voi! Se siete così fortunati ad avere questa opzione ...

Pace, -Al

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top