写入文件

时间:2016-09-02 15:42:41

标签: perl utf-8 cyrillic writetofile

我有一个包含字符串字段input的类,其中包含UTF-8字符。我的班级也有一个方法toString。我想使用方法toString将类的实例保存到文件中。问题是文件中写有奇怪的符号:

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":"здÑавейÑе"}

我使用flock来锁定/解锁文件。

3 个答案:

答案 0 :(得分:1)

我想你错过了 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()方法,因为我正在处理原生字符串,而不是真正的对象,但这并没有改变实质内容......

答案 1 :(得分:1)

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所属的类的代码,因此我无法帮助您解决此问题

您可以通过将open调用更改为

来解决此问题
open (my $fh, '>>', $dest) or die "Cannot open $dest : $!"

这将避免额外的编码步骤。但是你应该在你的Perl代码中使用未编码的字符:从正在读取的文件中删除任何编码,并在写入输出文件时根据需要编码输出数据。

答案 2 :(得分:0)

您的toString方法如何运作?我猜,根据你提供的输出,toString方法产生的是字节而不是字符,然后perl在尝试转换它时会感到困惑。

在打印之前尝试binmode STDOUT, ':encoding(UTF-8)',看它是否与文件产生相同的输出 - 否则你的测试是苹果和橘子。

如果它已经是字节而不是字符,那么您可以打开$dest而没有任何encoding(...)图层,这样就可以了。

一般来说,我发现在字符中使用字符非常痛苦,但是由于它解决了我不再需要考虑的更多极端情况,额外的工作变得值得,但这是额外的工作。 / p>