[SP-pm] Write Binary!
Igor Sutton Lopes
igor.sutton em gmail.com
Quinta Abril 26 09:42:44 PDT 2007
On Apr 26, 2007, at 5:19 PM, Igor Sutton Lopes wrote:
>
> 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 :-)
Bom, prá ler o arquivo binário gerado com este programa, você pode
utilizar o seguinte pedaço de código:
<code>
use strict;
use warnings;
use Data::Dumper;
open my $fh, "<", "/tmp/output.bin" or die $!;
binmode($fh);
my @contents = unpack( "f*", <$fh> );
my @data;
while (@contents) {
push @data, [ splice( @contents, 0, 5 ) ];
}
print Dumper \@data;
close $fh or warn $!;
</code>
Acredito que sabendo a dimensão N do seu array bidimensional, você
consegue até ler os seus arquivos gerados com os outros programas...
Para alterar o tamanho do array na representação, modifique o
terceiro argumento do comando splice() no código acima, modificando-o
para o tamanho N e diga-nos o resultado :-)
Boa sorte!
--
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/d56a5977/attachment-0001.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/d56a5977/attachment-0001.bin
Mais detalhes sobre a lista de discussão SaoPaulo-pm