Back-End

27 mar, 2013

Manipulando binários Cobol com Perl

Publicidade

Introdução

O mainframe que usa codificação EBCDIC internamente é usado por grandes corporações ao redor do mundo. No dia a dia, integrar esse tipo de sistema com a data warehouse envolve alguns desafios únicos.

imagem1

Neste artigo, será abordado como ler dados do binário COBOL.

Cobol Data File

O binário COBOL é um arquivo posicional em que a sequência dos bytes representa um dado, que pode ser dos seguintes tipos:

"A" para caracteres alpha  (A-Z, a-z, e espaços).
"9" para um campo numérico (apenas números 0-9) .
"X" qualquer caracter (incluindo binário).

O intuito deste artigo não é ensinar como programar em COBOL, é de apenas ensinar como ler. Quando um binário COBOL é gerado, não existe nenhuma informação que diga alguma informação sobre aquele dado. É necessário ter o que chamamos de COBOL Copy Book, que não é nada além de um texto que diz o tamanho de cada linha e o que os bytes representam. Dentro do binário COBOL não tem nada além de dados sem sentido. Para que eles façam sentido, é necessário um arquivo de “metainformação” dizendo o que cada posição representa.

imagem2

Por exemplo, vamos criar um arquivo binário com as seguintes posições:

"Copy Book"
9(4)
A(3)
A(3)

Bom, lendo o copy book, podemos saber que o tamanho de cada linha é de 10 bytes (4+3+3).

Vamos criar um binário fictício:

perl -MEncode 'binmode STDOUT;print encode("posix-bc","1234foobar5678foobar8765foobaz7485foobar")' \
> arquivo.cobol

Vamos salvá-lo como arquivo.cobol e agora vamos ler o arquivo.

#!/usr/bin/perl

use strict;
use warnings;
use Encode;

open my $fh,'<','arquivo.cobol' or die $!;
binmode $fh;

# - Cada linha tem 10 bytes 
my ($buff,$length) = (undef,10);
while(read($fh,$buff,$length)) {
    my $line = decode("posix-bc",$buff);
    print "Linha por linha $line\n";
}

Porém, no COBOL é comum comprimir os dados do tipo numérico pela metade (+1) usando Nibbles.

Nibbles

Se você estiver usando uma máquina byte addressable como a 80×86, para representar o número zero, por exemplo, será necessário usar 8 bits 00000000. Se você quiser manipular os bits individualmentes, será necessário pegar um byte inteiro e fazer isso manualmente. Um Nibble é o conjunto de 4 bits, portanto um byte tem dois nibbles.

imagem3

Com 4 bits, temos a possibilidade de fazer 16 diferentes combinações (2*4), e com 8 bits podemos ter 256 combinações (2*8) diferentes.

Como é muito extenso ler um nibble usando binário, utilizamos o sistema hexadecimal:

0123456789ABCDEF (16 caracteres)

Comp-3

Quando criamos um arquivo binário COBOL, nós temos a opção de comprimir os campos numéricos (tamanho/2 + 1).

Por exemplo, o número 999787 em hexadecimal seria 39 39 39 37 38 37, que ocuparia 6 bytes e teria 12 nibbles.

O que o comp-3 faz é o sistema inverso, ele grava 99 97 87 hexadecimal mais uma letra que indica se o número é positivo ou negativo, por isso a fórmula é (tamanho / 2 + 1). Resumindo, quando um campo for do tipo comp-3, será necessário pegar o valor em hexadeciamal que já será o valor real do número.

Por exemplo, 99 97 87 44 em hexadecimal será o número 999787 positivo, onde o 44 representa a letra D que diz que o número é positivo; se fosse a letra C, o número seria negativo.

Convert::IBM390

Para não ter que ficar fazendo as conversões usando “unpack” manualmente, existe o seguinte módulo, Convert::IBM390.

Referências

***

Artigo de Daniel de Oliveira Mantovani, publicado no Equinócio 2013 do grupo São Paulo Perl Mongers – http://sao-paulo.pm.org/equinocio/2013/mar/11-manipulando-binarios-cobol-com-perl

Texto sob Creative Commons – Atribuição – Partilha nos Mesmos Termos 3.0 Não Adaptada, mais informações em http://creativecommons.org/licenses/by-sa/3.0/