写入文件时奇怪地显示西里尔符号
Cyrillic symbols shown strangеly when writing to a file
我有一个 class,它有一个包含 UTF-8 字符的字符串字段 input
。我的 class 还有一个方法 toString
。我想使用方法 toString
将 class 的实例保存到文件中。问题是文件中写入了奇怪的符号:
my $dest = "output.txt";
print "\nBefore saving to file\n" . $message->toString() . "\n";
open (my $fh, '>>:encoding(UTF-8)', $dest)
or die "Cannot open $dest : $!";
lock($fh);
print $fh $message->toString();
unlock($fh);
close $fh;
第一次打印效果很好
Input: {"paramkey":"message","paramvalue":"здравейте"}
正在打印到控制台。问题是当我写入文件时:
Input: {"paramkey":"message","paramvalue":"здÑавейÑе"}
我为 locking/unlocking 文件使用了 flock
。
我想你错过了
use utf8;
在您的代码中...
此代码生成您期望的 "output.txt" 文件:
#!/usr/bin/perl
use strict;
use utf8;
my $dest = "output.txt";
my $message = "здравейте";
print "\nBefore saving to file\n" . $message . "\n";
open (my $fh, '>>:encoding(UTF-8)', $dest)
or die "Cannot open $dest : $!";
lock($fh);
print $fh $message;
close $fh;
我没有使用 toString()
方法,因为我正在处理原生字符串,而不是真实对象,但这不会改变实质...
您的 toString
方法如何运作?根据您提供的输出,我猜想 toString
方法生成的是字节而不是字符,然后 perl 在尝试转换它时会感到困惑。
在打印之前尝试 binmode STDOUT, ':encoding(UTF-8)'
看看它是否产生与文件相同的输出 - 否则你的测试是苹果和橘子。
如果它已经是字节而不是字符,您可以在没有任何 encoding(...)
层的情况下打开您的 $dest
,它会起作用。
总的来说,我发现在字节上处理字符非常痛苦,但由于它解决了更多我不必再考虑的极端情况,额外的工作变得值得,但这是额外的工作.
您的 toString
方法返回的字符串内容已经采用 UTF-8 编码。当您将它打印到您的终端时,它工作正常,因为它需要 UTF-8 数据。但是当您使用
打开输出文件时
open (my $fh, '>>:encoding(UTF-8)', $dest) or die "Cannot open $dest : $!"
您要求 Perl 应该重新编码数据为 UTF-8。这会将 UTF-8 编码数据的每个字节转换为单独的 UTF-8 序列,这根本不是您想要的。很遗憾,您没有显示 $message
所属的 class 的代码,所以我无法帮助您解决这个问题
您可以通过将 open
调用更改为仅
来解决此问题
open (my $fh, '>>', $dest) or die "Cannot open $dest : $!"
这将避免额外的编码步骤。但是您真的应该在整个 Perl 代码中使用未编码的字符:从您正在读取的文件中删除任何编码,并在写入输出文件时根据需要对输出数据进行编码。
我有一个 class,它有一个包含 UTF-8 字符的字符串字段 input
。我的 class 还有一个方法 toString
。我想使用方法 toString
将 class 的实例保存到文件中。问题是文件中写入了奇怪的符号:
my $dest = "output.txt";
print "\nBefore saving to file\n" . $message->toString() . "\n";
open (my $fh, '>>:encoding(UTF-8)', $dest)
or die "Cannot open $dest : $!";
lock($fh);
print $fh $message->toString();
unlock($fh);
close $fh;
第一次打印效果很好
Input: {"paramkey":"message","paramvalue":"здравейте"}
正在打印到控制台。问题是当我写入文件时:
Input: {"paramkey":"message","paramvalue":"здÑавейÑе"}
我为 locking/unlocking 文件使用了 flock
。
我想你错过了
use utf8;
在您的代码中...
此代码生成您期望的 "output.txt" 文件:
#!/usr/bin/perl
use strict;
use utf8;
my $dest = "output.txt";
my $message = "здравейте";
print "\nBefore saving to file\n" . $message . "\n";
open (my $fh, '>>:encoding(UTF-8)', $dest)
or die "Cannot open $dest : $!";
lock($fh);
print $fh $message;
close $fh;
我没有使用 toString()
方法,因为我正在处理原生字符串,而不是真实对象,但这不会改变实质...
您的 toString
方法如何运作?根据您提供的输出,我猜想 toString
方法生成的是字节而不是字符,然后 perl 在尝试转换它时会感到困惑。
在打印之前尝试 binmode STDOUT, ':encoding(UTF-8)'
看看它是否产生与文件相同的输出 - 否则你的测试是苹果和橘子。
如果它已经是字节而不是字符,您可以在没有任何 encoding(...)
层的情况下打开您的 $dest
,它会起作用。
总的来说,我发现在字节上处理字符非常痛苦,但由于它解决了更多我不必再考虑的极端情况,额外的工作变得值得,但这是额外的工作.
您的 toString
方法返回的字符串内容已经采用 UTF-8 编码。当您将它打印到您的终端时,它工作正常,因为它需要 UTF-8 数据。但是当您使用
open (my $fh, '>>:encoding(UTF-8)', $dest) or die "Cannot open $dest : $!"
您要求 Perl 应该重新编码数据为 UTF-8。这会将 UTF-8 编码数据的每个字节转换为单独的 UTF-8 序列,这根本不是您想要的。很遗憾,您没有显示 $message
所属的 class 的代码,所以我无法帮助您解决这个问题
您可以通过将 open
调用更改为仅
open (my $fh, '>>', $dest) or die "Cannot open $dest : $!"
这将避免额外的编码步骤。但是您真的应该在整个 Perl 代码中使用未编码的字符:从您正在读取的文件中删除任何编码,并在写入输出文件时根据需要对输出数据进行编码。