【问题标题】:Perl: printing Unicode strings to the Windows consolePerl:将 Unicode 字符串打印到 Windows 控制台
【发布时间】:2012-03-11 08:38:00
【问题描述】:

我在将 Unicode 字符串打印到 Windows 控制台时遇到了一个奇怪的问题*。

考虑一下这段文字:

אני רוצה לישון

Intermediary

היא רוצה לישון
אתם, הם
Bye
Hello, world!
test

假设它在一个名为“file.txt”的文件中。

当我去*:“type file.txt”时,它打印得很好。但是当它从 Perl 程序中打印出来时,像这样:

 use strict;
 use warnings;
 use Encode;
 use 5.014;
 use utf8;
 use autodie;
 use warnings    qw< FATAL  utf8     >;
 use open        qw< :std  :utf8     >;
 use feature     qw< unicode_strings >;
 use warnings 'all';

 binmode STDOUT, ':utf8';   # output should be in UTF-8
 my $word;
 my @array = ( 'אני רוצה לישון', 'Intermediary',
    'היא רוצה לישון', 'אתם, הם', 'Bye','Hello, world!', 'test');
 foreach $word(@array) {
    say $word;
 }

Unicode 行(在本例中为希伯来语)每次都会再次出现,部分中断,如下所示:

E:\My Documents\Technical\Perl>perl "hello unicode.pl"
אני רוצה לישון
לישון
�ן

Intermediary
היא רוצה לישון
לישון
�ן

אתם, הם
�ם

Bye
Hello, world!
test

(我将所有内容都保存为 UTF-8)。

这很奇怪。有什么建议吗?

(这不是“Console2”问题* - 相同的问题出现在“常规”Windows 控制台上,只是您看不到希伯来字形)。


* 使用“Console”(也称为“Console2”) - 这是一个不错的小实用程序,可以在 Windows 控制台中使用 Unicode - 例如,请参见此处: http://www.hanselman.com/blog/Console2ABetterWindowsCommandPrompt.aspx

** 注意:在控制台,你当然要说:

chcp 65001

【问题讨论】:

  • 这些 Unicode 字符串,以 UTF-8 表示。请取消您的 -1。
  • 很抱歉浪费了所有转义代码的精力,但在 Markdown 中,格式化代码所需要做的就是缩进 4 个空格。您也可以只按编辑器工具栏中的代码按钮{}。 (@sarnold:已修复!)
  • Helen:看看@minitech 如何在revisions 中重新格式化您的帖子(可通过“N 分钟前编辑”链接在每个帖子上获得)- 将来修改起来要容易得多,复制并粘贴到其他地方,并使用更整洁的格式样式。微型技术,非常感谢。再次。 :)
  • 在一行前面至少放四个空格。 markdown 解析器会认为它是在代码样式中呈现的东西。通常,我在文本编辑器中输入我的帖子,然后将代码位移动一个缩进级别,然后再粘贴。
  • @TLP - 如果只有一个网站可以让人们询问与编程相关的question... :))))) (投票最高的答案列表&gt; 命令)

标签: perl unicode utf-8 console unicode-string


【解决方案1】:

此外,在使用 ConEmu 时不会出现这种行为,这也会在 Windows 的命令控制台中启用正确的 Unicode 支持。

【讨论】:

    【解决方案2】:

    伙计们:继续研究 Perlmonks 的帖子,结果发现它更简洁、更好: 替换:
    use Win32::API;
    和:

    $SetConsoleOutputCP= new Win32::API( 'kernel32.dll', 'SetConsoleOutputCP', 'N','N' );
    $SetConsoleOutputCP->Call(65001);
    

    与:

    use Win32::Console;
    

    和:

     Win32::Console::OutputCP(65001);
    

    保持其他所有内容不变。
    这更符合 Perl 简洁和神奇的精神。

    【讨论】:

    • 另外必须将cmd.exe的字体改为“Consolas”才能看到unicode字符。
    【解决方案3】:

    您还可以利用Win32::Unicode::ConsoleWin32::Unicode::Native 在windows 控制台上实现unicode 打印。

    【讨论】:

      【解决方案4】:

      您尝试过perlmonk 的解决方案吗?

      它也使用:unix 来避免控制台缓冲区。

      这是来自该链接的代码:

      use Win32::API;
      
      binmode(STDOUT, ":unix:utf8");
      
      #Must set the console code page to UTF8
      $SetConsoleOutputCP= new Win32::API( 'kernel32.dll', 'SetConsoleOutputCP', 'N','N' );
      $SetConsoleOutputCP->Call(65001);
      
      $line1="\x{2554}".("\x{2550}"x15)."\x{2557}\n";
      $line2="\x{2551}".(" "x15)."\x{2551}\n";
      $line3="\x{255A}".("\x{2550}"x15)."\x{255D}";
      $unicode_string=$line1.$line2.$line3;
      
      print "THIS IS THE CORRECT EXAMPLE OUTPUT IN PURE PERL: \n";
      print $unicode_string;
      

      【讨论】:

      • 哇 - 很多有趣的东西。我会研究它,尝试它并报告。
      • 她已经将控制台设置为 cp 65001,那么该帖子中有什么新内容?
      • @J-16-SDiZ 谢谢大家 - 它工作得很好。它仍然抛出错误:"Global symbol "$SetConsoleOutputCP" requires explicit package name",但很容易通过将其替换为:Win32::$SetConsoleOutputCP
      • @ikegami: chcp 65001 是不够的。Windows 控制台缓冲区和 Perl 缓冲区不一致,对于 Perl Unicode 输出,您必须指定:binmode(STDOUT, ":unix:utf8");(而不是:binmode(STDOUT, ":utf8");)到 Windows 控制台工作。
      • --之前的评论应该是:$Win32::SetConsoleOutputCP 而不是:Win32::$SetConsoleOutputCP
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-17
      • 1970-01-01
      • 2015-04-15
      相关资源
      最近更新 更多