eccodes/tools/grib_split.pl

156 lines
4.1 KiB
Perl
Raw Normal View History

2013-03-25 12:04:10 +00:00
#!/usr/bin/perl
use strict;
2023-12-04 18:18:21 +00:00
# ----------------------------------------------------------------------
# Convert GRIB edition 2 multi-field (several fields per message) files
# to single-field (one field per message)
# ----------------------------------------------------------------------
2013-03-25 12:04:10 +00:00
my $debug = 0;
my $total = 0;
my $previous_bitmap;
2023-12-04 18:25:19 +00:00
if ($ARGV[0] eq "-d")
2013-03-25 12:04:10 +00:00
{
2023-12-04 18:25:19 +00:00
$debug = 1;
shift @ARGV;
2013-03-25 12:04:10 +00:00
}
my $out = pop @ARGV;
unless(@ARGV >= 1 && defined $out)
{
2023-12-04 18:25:19 +00:00
print STDERR "Usage: $0 [-d] in1 [in2 ...] out\n";
exit(1);
2013-03-25 12:04:10 +00:00
}
open(OUT,">$out") || die "$out: $!";
foreach my $in ( @ARGV )
{
2023-12-04 18:25:19 +00:00
my $gribs = 0;
my $cnt = 0;
open(IN,"<$in") || die "$in: $!";
while(1)
{
my @sections = ();
# Find header
print "Looking for GRIB\n" if ($debug);
my $grib;
while((read(IN,$grib,4) == 4) && ($grib ne "GRIB"))
{
seek(IN,-3,1);
}
unless($grib eq "GRIB")
{
print "No more GRIBs\n" if ($debug);
last;
}
my $here = tell(IN);
my $start = $here - 4;
$gribs++;
print "$grib found at offset $start\n" if ($debug);
my ($reserved,$discipline,$edition);
die "$in: $!" unless(read(IN,$reserved,2) == 2);
die "$in: $!" unless(read(IN,$discipline,1) == 1);
die "$in: $!" unless(read(IN,$edition,1) == 1);
my $grib_edition = ord($edition);
die "Un-supported edition $grib_edition" unless($grib_edition == 2);
my ($len1,$len2);
die "$in: $!" unless(read(IN,$len1,4) == 4);
die "$in: $!" unless(read(IN,$len2,4) == 4);
my $msglen1 = unpack("N",$len1); die "GRIB too large" if ($msglen1);
my $msglen2 = unpack("N",$len2);
my $msglen = $msglen2;
print "Message length $msglen\n" if ($debug);
while(1)
{
$here = tell(IN);
my ($seclen,$section);
die "$in: $!" unless(read(IN,$seclen,4) == 4);
if ($seclen eq "7777")
{
print "7777 found at offset $here\n" if ($debug);
die "Invalid message lenth $msglen"
unless($here+4-$start == $msglen);
last;
}
$seclen = unpack("N",$seclen);
die "$in: $!" unless(read(IN,$section,1) == 1);
$section = ord($section);
die "Invalid section number $section" unless ($section >= 1 && $section <=7);
print "Section $section found at offset $here length $seclen\n" if ($debug);
seek(IN,-5,1) or die "$in: $!";
my $data;
die "$in: $!" unless(read(IN,$data,$seclen) == $seclen);
if ($section == 6)
{
# Special case for inherited bitmaps
if (unpack('C',substr($data,5,1)) == 254)
{
die "No previous bitmap" unless(defined $previous_bitmap);
$data = $previous_bitmap;
}
else
{
$previous_bitmap = $data;
}
}
splice(@sections,$section+1);
$sections[$section] = $data;
if ($section == 7)
{
print OUT "GRIB";
print OUT $reserved;
print OUT $discipline;
print OUT $edition;
print OUT $len1;
$len2 = 16 + 4;
for(my $i = 1; $i <= 7 ; $i++)
{
$len2 += length($sections[$i])
if (defined $sections[$i]);
}
$cnt++;
print "GRIB $cnt is $len2\n" if ($debug);
$len2 = pack("N",$len2);
print OUT $len2;
for(my $i = 1; $i <= 7 ; $i++)
{
next unless(defined $sections[$i]);
print OUT $sections[$i];
}
print OUT "7777";
}
}
}
print "$in: $cnt field(s) found in $gribs GRIB(s)\n";
$total += $cnt;
2013-03-25 12:04:10 +00:00
}
close(OUT) or die "$out: $!";
print "$out: $total field(s) written\n";