[SP-pm] Write Binary!

Igor Sutton Lopes igor.sutton em gmail.com
Quinta Abril 26 09:19:15 PDT 2007


On Apr 26, 2007, at 4:43 PM, Henrique Rennó wrote:

> Fala Fred!
>
> Existe um programa muito usado aqui no trabalho chamado GrADS.  
> Basicamente ele é um plotador, um gerador de gráficos. Para ele  
> plotar os gráficos, os valores a serem trabalhados devem estar em  
> um arquivo no formato binário (existem outros formatos que ele lê  
> também mas binário é o mais geral).
>
> Os programas que faço para trabalhar com esses dados estão todos em  
> C que passei dos que estavam em FORTRAN. No FORTRAN deve-se abrir o  
> arquivo passando parâmetros tipo 'stream' and 'unformatted', sem  
> esses parâmetros não dá certo. Já em C seria apenas a opção "b"  
> para o fopen. Para escrever no arquivo, em FORTRAN usa-se o write  
> passando para ele um vetor(M*N) onde N é o número de elementos da  
> matriz de 2 dimensões com M linhas e N colunas na ordem linha 1,  
> colunas 1-N, linha2, colunas 1-N, ..., linhaM, colunas 1-N, etc. Em  
> C não dá certo usando o fscanf ou qualquer outra função que utiliza  
> formatação, já o fwrite funciona como eu havia descrito antes:  
> fwrite(matriz, sizeof(float), M*N, fpointer)
>
> Agora estou querendo passar para perl apenas por aprendizado.  
> Tentei o pack com formatação "B*" como o Luis Motta disse e não  
> funcionou.
>

Vamos lá, você quer armazenar um array mais ou menos assim:

@data = (
     [ 0, 1, 2, 3, 4 ], # linha1
     [ 0, 1, 2, 3, 4 ], # linha2
     [ 0, 1, 2, 3, 4 ], # linhaN
);

em formato binário, certo?

Segundo a página manual do fwrite(3):

      [snip]

      size_t
      fwrite(const void * restrict ptr, size_t size, size_t nmemb,
          FILE * restrict stream);

     [snip]

      The function fwrite() writes nmemb objects, each size bytes  
long, to the
      stream pointed to by stream, obtaining them from the location  
given by
      ptr.

Acredito que uma primeira tentativa seria:

<code>
use strict;
use warnings;

my @data = (
     [ 0, 1, 2, 3, 4 ],    # linha1
     [ 0, 1, 2, 3, 4 ],    # linha2
     [ 0, 1, 2, 3, 4 ],    # linhaN
);

my $binary_data;
for my $line (@data) {

     # cria o pattern para o pack, baseado no numero
     # de elementos que este possui. perldoc -f pack para
     # significado de "f"
     my $pack_pattern = "f" x scalar @{$line};

     # armazena o resultado do pack aplicado ao
     # pattern acima, utilizando os elementos da
     # linha
     $binary_data .= pack( $pack_pattern, @$line );
}
open my $fh, ">", "/tmp/output.bin" or die $!;
binmode($fh);
print $fh $binary_data;
close $fh or warn $!;
</code>

Veja se serve prá alguma coisa, ou chega perto :-)

--
Igor Sutton
igor.sutton em gmail.com



-------------- Próxima Parte ----------
Um anexo em HTML foi limpo...
URL: http://mail.pm.org/pipermail/saopaulo-pm/attachments/20070426/cea95fd8/attachment.html 
-------------- Próxima Parte ----------
Um anexo não texto foi limpo...
Nome  : PGP.sig
Tipo  : application/pgp-signature
Tam   : 186 bytes
Descr.: This is a digitally signed message part
Url   : http://mail.pm.org/pipermail/saopaulo-pm/attachments/20070426/cea95fd8/attachment.bin 


Mais detalhes sobre a lista de discussão SaoPaulo-pm