Search code examples
perlutf-8localbinmode

"Turn Off" binmode(STDOUT, ":utf8") Locally


I Have The following block in the beginning of my script:

#!/usr/bin/perl5 -w
use strict;
binmode(STDIN, ":utf8");
binmode(STDOUT, ":utf8");
binmode(STDERR, ":utf8");

In some subroutines when there is other encoding(from a distant subroutine), the data will not display correctly, when receiving cyrillic or other characters. It is the "binmode", that causes the problem.

Can I "turn off" the binmode utf8 locally, for the subroutine only?

I can't remove the global binmode setting and I can't change the distant encoding.


Solution

  • One way to achieve this is to "dup" the STD handle, set the duplicated filehandle to use the :raw layer, and assign it to a local version of the STD handle. For example, the following code

    binmode(STDOUT, ':utf8');
    print(join(', ', PerlIO::get_layers(STDOUT)), "\n");
    
    {
        open(my $duped, '>&', STDOUT);
        # The ':raw' argument could also be omitted.
        binmode($duped, ':raw');
        local *STDOUT = $duped;
        print(join(', ', PerlIO::get_layers(STDOUT)), "\n");
        close($duped);
    }
    
    print(join(', ', PerlIO::get_layers(STDOUT)), "\n");
    

    prints

    unix, perlio, utf8
    unix, perlio
    unix, perlio, utf8
    

    on my system.