【问题标题】:Perl - Convert PC UTF-8 to PC ANSIPerl - 将 PC UTF-8 转换为 PC ANSI
【发布时间】:2013-02-11 04:44:07
【问题描述】:

我有一个以 PC UTF-8 编码的文件。我想将文件转换为 PC ANSI。

我已经尝试了以下,但我总是得到输出文件是 PC UTF-8。

use Encode;

$infile = $ARGV[0];
open(INFILE, $infile);

my $outfile = "temp.txt";

open(OUTFILE, ">$outfile");

while(<INFILE>) {
  my $row = $_;
  chomp $row;

  $row = Encode::encode("Windows-1252", $row);
  print OUTFILE $row."\n";

}

close INFILE;
close OUTFILE;

【问题讨论】:

  • chomp 行加上\n有点浪费。
  • 你能用一个 very 的小文件试试吗,比如 1 行带有单个非 ASCII 字符的短行,然后向我们展示输入和输出的十六进制转储?
  • 这与您的问题无关,但首选 open 的 3 参数版本。 modernperlbooks.com/mt/2010/04/…

标签: perl unicode ansi


【解决方案1】:

问题是您从不解码您编码的数据。

use strict;
use warnings;
use Encode qw( encode decode );

open(my $INFILE,  '<', $ARGV[0]) or die $!;
open(my $OUTFILE, '>', $ARGV[1]) or die $!;

while (my $utf8 = <$INFILE>) {
   my $code_points = decode('UTF-8', $utf8);    # <-- This was missing.
   my $cp1252 = encode('cp1252', $code_points);
   print $OUTFILE $cp1252;
}

但是你可以更容易地做到这一点:

use strict;
use warnings;

open(my $INFILE,  '<:encoding(UTF-8)',  $ARGV[0]) or die $!;
open(my $OUTFILE, '>:encoding(cp1252)', $ARGV[1]) or die $!;

while (<$INFILE>) {
   print $OUTFILE $_;
}

【讨论】:

  • cp1252 只是Windows-1252 的一种更短的写法)
  • 这似乎有效。我刚收到一条消息,“\x{feff}”没有映射到 cp1252”。有什么好的过滤方法吗?
  • 如果这是唯一的问题字符,您可以使用s/^\x{FEFF}//;(解码后)安全地摆脱它。这是BOM
  • 转码和替换某些内容的情况并不罕见,例如,如果您正在处理在 HTML 等元数据中包含编码的文件。
【解决方案2】:

您应该使用 PerlIO-Layers,而不是手动进行解码和编码。您可以使用binmode 函数指定层,或者在三参数open 的模式参数中:

use strict; use warnings;
use autodie;

open my $INFILE,  '<:utf8',                 $ARGV[0];
open my $OUTFILE, '>:encoding(iso-8859-1)', "temp.txt";
#                   ^-- the layers

while (my $line = <$INFILE>) {
  print $OUTFILE $line;
}

请注意,Perl 默认不会以 UTF8 格式打开文件,您还必须指定解码层。 :encoding(utf8)这个层太常见了,你可以直接说:utf8

您可以列出所有可用的编码

use Encode;
print "$_\n" for Encode->encodings();

【讨论】:

  • @user333746 ①检查可用编码列表,看看你当前安装了什么。 ②请将您的代码与我更新的帖子进行比较;该层是:encoding(foo-bar)(我最初的帖子有错误)。 ③ 你运行的是什么版本的perl?为什么是eval——你在 mod_perl 下吗?
  • 您为什么从 Windows-1252 更改为 iso-8859-1?它们不一样,OP明确表示他想要“ANSI”编码(Windows称之为单字节本地编码,在大多数机器上是Windows-1252 aka cp1252,neve iso-8859-1) .
猜你喜欢
  • 1970-01-01
  • 2019-02-10
  • 1970-01-01
  • 2015-10-06
  • 2013-12-14
  • 2012-01-08
  • 2015-11-22
  • 2023-03-19
  • 1970-01-01
相关资源
最近更新 更多