in reply to Re: Error binmode() on unopened filehandle
in thread Error binmode() on unopened filehandle

Once you go to BINMODE on a file handle, a record separator makes no sense.

Maybe you should have tested this.

#!/usr/bin/perl use strict; use warnings; binmode DATA; my $binary = <DATA>; print "$binary\n"; __DATA__ first second
This gives:
first

Greetings,
-jo

$gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$

Replies are listed 'Best First'.
Re^3: Error binmode() on unopened filehandle
by Marshall (Canon) on May 03, 2020 at 14:26 UTC
    Ok, I tested with a .jpg file I had laying around.
    use warnings; use strict; open (my $fh, '<', "COVID19-Death02Apr.jpg") or die "$!"; binmode $fh; my $binary = <$fh>; #entire binary file goes to Perl variable print '',$binary;
    Works just fine!

    What you are overlooking is that you must set binmode before reading from the file. The Perl DATA file handle is an open file handle to the Perl program source that is seeked to the first character on the next line after __DATA__. This is buffered character mode I/O. You can't switch modes in the midst of a file.

      You can't switch modes in the midst of a file.

      You sure can:

      use warnings;
      use strict;
      use utf8;
      use Data::Dumper;
      $Data::Dumper::Useqq=1;
      
      print join(", ",PerlIO::get_layers(*DATA)),"\n";
      print Dumper( scalar <DATA> );
      binmode DATA;
      print join(", ",PerlIO::get_layers(*DATA)),"\n";
      print Dumper( scalar <DATA> );
      
      __DATA__
      H∃llⓄ, 🗺!
      H∃llⓄ, 🗺!
      

      Output:

      unix, perlio, utf8 $VAR1 = "H\x{2203}ll\x{24c4}, \x{1f5fa}!\n"; unix, perlio $VAR1 = "H\342\210\203ll\342\223\204, \360\237\227\272!\n";
        Ok. But I refer you to https://perldoc.perl.org/functions/binmode.html.
        In general, binmode should be called after open but before any I/O is done on the filehandle.
        Yes, there are some exceptions to this "rule". But I figure this "rule" is a good one.

      I disagree. What about this:

      #!/usr/bin/perl use strict; use warnings; my $data = <<EOF; first second EOF open my $fh, '<', \$data; binmode $fh; my $binary = <$fh>; print "$binary\n";

      Greetings,
      -jo

      $gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
        Ok, spent some more time fiddling with this. I now see what you mean (code attached).
        I have never read a binary file with the <> angle operator. That idea would have never have occured to me. I have always used a read() specifying the num of bytes to read as shown below. This implies that although this "angle read" appeared to work in my .jpg example, there could be some CRLF sequence in the data that would cause this .jpg read to fail. I find that interesting to know. Good point.

        I guess bottom line: Don't use <> bracket when reading binary files!

        #!/usr/bin/perl use strict; use warnings; my $data = <<EOF; first second EOF print "data var in text mode - this works...\n"; print "$data\n"; print "----\n"; open my $fh, '<', \$data; binmode $fh; my $num_bytes = read ($fh, my $buf, 20000); print "read () binary doesn't completely work..the normal way to read +binary\n"; print "this is Windows machine and I don't see both CR and LF characte +rs\n"; print "but I think that is due to Perl translation of line endings\n"; print "bytes read = $num_bytes\n"; print '',$buf; print "----\n"; print "using angle operator for binary read doesn't work\n"; print "I've never tried this before and I'm not sure why\n"; print "this doesn't work - need explanation of the angle <>op.\n"; close $fh; open $fh, '<', \$data or die "$!"; binmode $fh; my $bdata = <$fh>; print '',$bdata; __END__ data var in text mode - this works... first second ---- read () binary doesn't completely work..the normal way to read binary this is Windows machine and I don't see both CR and LF characters but I think that is due to Perl translation of line endings bytes read = 13 first second ---- using angle operator for binary read doesn't work I've never tried this before and I'm not sure why this doesn't work - need explanation of the angle <>op. first
        I don't understand the point that you are trying to make. You open a file handle to a Perl var. That's fine. You set binmode before you read from that file handle and that's fine too.

        Find some .jpg file you have somewhere and try the code that I posted. Use of the DATA file handle is "special".

        Your initial premise that you could read binary data from the DATA file handle is wrong. That data will be in a character format.

        Update: Here is a Perl program that reads and prints itself. DATA is an already read and opened file handle.

        use warnings; use strict; print "testing seek of DATA handle\n"; print "this will print this program\n"; seek (DATA,0,0); my $text = do{ local $/ = undef; <DATA>; }; print $text; __DATA__ asdfasdf asdfasdf

      Works just fine!

      That will only read until the first 0A byte. You need local $/;