1

I would like to convert some data in binary using Perl. The data needs to be output in 8 bits binary. The original data comes in this format:

137.0000
136.0000
133.0000
136.0000
10.0000
134.0000
0.0000
132.0000
132.0000

To do so, I transformed the data to suppress the ".0000" then I use the pack function with the option C* (this format correspond to an "unsigned character (usually 8 bits)" according to the documentation). I called this file txt2bin.pl:

my $file = $ARGV[0];
my $fileout = $file.".bin";

if($file eq "-h" or $file eq "-help" or $file eq "")
{  
    print "Usage : txt2bin.pl file_in\n";
    print "        file_out = file_in.bin\n";
    print "This script converts a txt file to a binary file\n";

}

else
{
  print "File in = $file\n";
  print "File out = $fileout\n";

  open(FILE,"<$file") or die $!;
  open(FILEOUT,">$fileout") or die $!;
    binmode FILEOUT;
    while(defined(my $line=<FILE>))
    {
      chomp($line);
      $line =~ s/\.0000//;
      syswrite FILEOUT, pack("C*",$line);
    }
  close(FILE);
  close(FILEOUT);
}

I also need to be able to do the reverse operation, so, I created another file bin2txt.pl:

my $file = $ARGV[0];
my $fileout = $file.".txt";

if($file eq "-h" or $file eq "-help" or $file eq "")
{
    print "Usage : bin2txt.pl file_in\n";
    print "        file_out = file_in.txt\n";
    print "This script converts a binairy file to a txt file\n";
}

else
{
  print "File in = $file\n";
  print "File out = $fileout\n";

  my $file = "<$file";

  # undef $/ to read whole file in one go
  undef $/;

  open(FILE,$file) or die $!;
  open(FILEOUT,">$fileout") or die $!;

  # binmode FILE to supress conversion of line endings
  binmode FILE;

  my $data = <FILE>;
  $data =~ s/(.{1})/unpack("C*",$1).".0000 \n"/eg;
  syswrite FILEOUT, $data;
}

However, when I execute the first program txt2bin.pl, then the second, I should get:

137.0000
136.0000
133.0000
136.0000
10.0000
134.0000
0.0000
132.0000
132.0000

Instead, of that, I get this:

137.0000
136.0000
133.0000
136.0000

134.0000
0.0000
132.0000
132.0000

The 10.0000 does not show up, do you guys have any idea about this ? Thanks for helping.

4
  • 1
    Probably the 10 is taken as a new line character 0x0a somehow? Commented Jun 19, 2019 at 13:28
  • @HåkonHægland, but why is it the only one ? And how to prevent that ? Commented Jun 19, 2019 at 13:36
  • Note that the {1} is useless. Commented Jun 19, 2019 at 19:23
  • I know, in other part of my code (not shown above), I have {3}, for more genericity, I keept the {1}. Thanks for the remarks anyway :-) Commented Jun 20, 2019 at 15:11

1 Answer 1

2

You need to add the s modifier to the regexp substitution in order to match a 10 (newline) :

$data =~ s/(.{1})/unpack("C*",$1).".0000 \n"/seg;

From perldoc perlre :

s
Treat the string as single line. That is, change "." to match any character whatsoever, even a newline, which normally it would not match.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.