Pergunta

estou usando A implementação EBCDIC de Jon Skeet na .NET Para ler um arquivo vsam baixado no modo binário com FTP de um sistema de mainframe. Funciona muito bem para ler/escrever nesta codificação, mas não tem nada para ler valores de decimais embalados. Meu arquivo os contém, e eu preciso descompactá -los (com o custo de mais bytes, obviamente).

Como posso fazer isso?

Meus campos são definidos como PIC S9(7)V99 COMP-3.

Foi útil?

Solução

Ahh, BCD. Buzina se você o usou na montagem 6502.

Claro, a melhor aposta é deixar o Cobol se mover fazer o trabalho para você! Uma dessas possibilidades pode ajudar.

(Possibilidade nº 1) Supondo que você tenha acesso ao mainframe e ao código -fonte, e o arquivo de saída é apenas para seu uso, modifique o programa para que ele apenas mova o valor para um PIC S9 (7) V99 sem embalagem simples.

(Possibilidade nº 2) Supondo que não seja tão fácil, (por exemplo, o arquivo é inserido para outros PGMs ou não pode alterar o código), você pode escrever outro programa COBOL no sistema que lê esse arquivo e grava outro. Corte e cole o layout de registro do arquivo com o BCD no novo programa para arquivos de entrada e saída. Modifique a versão de saída para não ser embalada. Leia um registro, faça um 'movimento correspondente' para transferir os dados e escreva até o EOF. Em seguida, transfira este Arquivo.

(Possibilidade nº 3) Se você não puder tocar no mainframe, observe a descrição no artigo que você vinculou no seu comentário. O BCD é relativamente simples. Isto poderia Seja tão fácil quanto este (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

Eu testei com algumas variações desta chamada:

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

Por exemplo, é -40.1. Mas apenas alguns. Portanto, ainda pode estar errado.

Então, se o seu Comp-3 iniciar, digamos, no byte 10 do layout do registro de entrada, isso resolveria:

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

Observando as fórmulas do artigo de conversão de dados para o número de bytes enviar e o número dos 9 antes e depois do V.

Armazene o resultado em um decimal para evitar erros de arredondamento. ESP se for $$$. Float & Double vai causar sua dor! Se você não está processando, mesmo uma string é melhor.

Claro poderia Seja mais difícil. Onde eu trabalho, o mainframe é de 9 bits por byte. Sério. É isso que torna as duas primeiras possibilidades tão salientes. É claro que o que realmente os torna melhores é o fato de que você pode ser um programador apenas para PC e essa é uma ótima desculpa para fazer com que um programador de mainframe faça o trabalho para você! Se você tem muita sorte de ter essa opção ...

Paz, -al

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top