Re^4: Error binmode() on unopened filehandle
by haukex (Archbishop) on May 03, 2020 at 15:55 UTC
|
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";
| [reply] [d/l] |
|
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.
| [reply] |
Re^4: Error binmode() on unopened filehandle
by jo37 (Deacon) on May 03, 2020 at 14:32 UTC
|
#!/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$
| [reply] [d/l] |
|
#!/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
| [reply] [d/l] |
|
Once you go to BINMODE on a file handle, a record separator makes no sense.
I think I understand where you're coming from: when reading a binary file, it often makes more sense to use read instead of readline (aka <>), and I personally would probably use the former.
However, I also see several incorrect statements mixed in your nodes, like "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." - this is wrong, see my node here.
I guess bottom line: Don't use <> bracket when reading binary files!
DATA is just another filehandle, and readline is not that magical, it can be used to read any filehandle (whether DATA, a binary file, etc.), as long as you pay attention to $/. For example, you can set $/ to a reference to an integer, and then readline will read "records" from the file, very much like read does.
Update:
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";
binmode turns off the CRLF to LF conversion, so if you're not seeing CRLF line endings (not sure how you determined that?) then that means the source file has only LF instead of CRLF line endings. Update 2: Hmm, see replies.
Minor edits for clarity.
| [reply] [d/l] [select] |
|
|
|
|
|
|
| [reply] [d/l] [select] |
|
binmode $fh;
read($fh, my $buf, 20000);
and
binmode $fh;
local $/ = \20000;
my $buf = <$fh>;
Of course, both are junk. Why would you only read the first 20,000 bytes? The following make more sense:
binmode $fh;
my $file = '';
1 while read($fh, $file, 8*1024, length($file));
or
binmode $fh;
local $/;
my $file = <$fh>;
| [reply] [d/l] [select] |
|
|
|
|
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
| [reply] [d/l] |
|
#!/usr/bin/perl
use strict;
use warnings;
use constant RANDFILE => "rand.dat";
system "dd if=/dev/urandom of=" . RANDFILE . " bs=1k count=64";
open my $fh, '<', RANDFILE or die;
binmode $fh;
my $binary = <$fh>;
print "got: ", length($binary), "\n";
Greetings, -jo
$gryYup$d0ylprbpriprrYpkJl2xyl~rzg??P~5lp2hyl0p$
| [reply] [d/l] [select] |
|
use feature qw( say );
binmode DATA if $ARGV[0];
while (<DATA>) {
say sprintf "%v02X", $_;
}
__DATA__
abc
def
>perl a.pl 0
61.62.63.0A
64.65.66.0A
>perl a.pl 1
61.62.63.0D.0A
64.65.66.0D.0A
| [reply] [d/l] [select] |
Re^4: Error binmode() on unopened filehandle
by ikegami (Patriarch) on May 04, 2020 at 03:29 UTC
|
| [reply] [d/l] |