Perl 确保我对utf8的处理是正确的

Perl 确保我对utf8的处理是正确的,perl,Perl,我将Perl用于处理大量Unicode文档的模块。我开始感到紧张,因为我没有打开和关闭带有utf8层的文件,比如open(OUT,“>:utf8',$textfile)。然而,我已经进行了彻底的测试,输出仍然如预期的那样。所以我想更好地理解为什么 简而言之,我的Perl模块将文档传递给外部服务并获得响应。响应将采用Utf8格式。它为此使用LWP::UserAgent。当它得到响应时,它只是将其写入一个文件: my $fh; open($fh, '>', $outputpath) or di

我将Perl用于处理大量Unicode文档的模块。我开始感到紧张,因为我没有打开和关闭带有utf8层的文件,比如
open(OUT,“>:utf8',$textfile)
。然而,我已经进行了彻底的测试,输出仍然如预期的那样。所以我想更好地理解为什么

简而言之,我的Perl模块将文档传递给外部服务并获得响应。响应将采用Utf8格式。它为此使用LWP::UserAgent。当它得到响应时,它只是将其写入一个文件:

my $fh;
open($fh, '>', $outputpath) or die "Could not open file '$outputpath' $!";
print $fh $response->content;
close $fh;
我将这些文件与表示“预期”输出的Unicode文件进行了区分,这很好。但是,您可以在我的open命令中看到,我没有使用utf8层。那为什么呢

如果我只是将$response->content返回到其他进程,而不是打印它呢?那还是合适的吗


我还有一个单独的过程,我想问一个非常类似的问题。在本例中,我尝试构建一个新的服务来替换旧的服务。旧版本从类似于
open(my$fh':utf8',$outputfile)
的文件中读取。新服务仍将以相同的方式读取,但不再写入输出文件。它将使用HTTP将字符串发送到另一台服务器,并在该服务器上使用
open(my$fh,'>',$outputfile)
将字符串打印到一个文件中,因此没有utf8层。我不能马上改变密码

我希望文件内容与其他方式完全相同(其他处理规则都没有改变)。我应该为失去图层而紧张吗

我想如果我能更好地理解这些层在做什么,也许会有所帮助。

在主要问题中没有“处理utf8”,这本身就是不对的

整个过程都在运行,因为服务器按照您所说的方式发送utf8,如下所示


$response
上使用的
内容
方法来自

如果给定参数,content()方法将设置原始内容。如果没有给出参数,则不涉及内容。无论哪种情况,都会返回原始内容

由于您没有指定层†,因此默认情况下使用的层可能是unix的
:unix:perlio
,没有编码(请参阅)。因此,您正在将原始字节转储到磁盘,保持不变

再往下看,在
解码内容(%options)
,我们看到了默认设置

default\u字符集

这将覆盖content_charset()猜测的默认字符集,或者如果该操作失败,“ISO-8859-1”

并且可以通过打印来确定您得到了什么

say 'Content type: ', $response->content_charset;
您应该在哪里获得
内容类型:UTF-8
。但是,如果您从服务器接收到不同的编码,那么这将在文件中结束,任何期望utf8的代码都将中断

人们应该总是对所有输入进行解码,并对所有输出进行编码。然后我们就知道到底发生了什么。当输入被解码时,程序将使用字符串(而不是发送的任何编码中的字节)进行处理。最后,对输出进行适当的编码。这应该是有用的。在这里,您可以使用
解码的内容
,并编写用
:encoding(UTF-8)
打开的文件

对于
使用open:std“,”:encoding(UTF-8)”此杂注词法范围内的所有I/O都将作为utf8处理。(这可以被其他特定用途覆盖,比如在三个打开的参数中指定图层。)
看

至于另一个问题,您需要正确地编码您打算“发送到另一台服务器”的内容。如何做到这一点取决于您如何“发送”它


†通过I/O,可以设置“层”,以便在读取或写入数据时,根据需要在后台对输入和输出进行编码。这项工作是由我来完成的。有关该过程的详细说明,请参阅。
另请参见和。

是否设置了
PERL\u UNICODE
环境变量?您的代码中有任何
使用open
语句吗?
content
方法来自,并且由它返回“原始内容”,因此您将字节转储到文件中。(对输入进行解码并对输出进行编码是一条通用规则。)至于另一个问题,您将如何“使用HTTP将字符串发送到另一台服务器”?它通过HTTP发送的方式非常复杂,但基本上是PSGI响应。我的问题的主要部分是,utf8层实际上在做什么。它是如何改变输入或输出上的数据的?我在解码输入和编码输出时看到的问题是:如果我正在编写的输入已经是Utf8格式的,然后我使用层“Utf8”编写它,我会双重编码并创建jibberish吗?@Stephen,是的,但正确的修复方法不是删除编码层;它正在解码你的输入。您不应该使用编码文本(例如,使用UTF-8编码的文本);您应该使用解码文本(Unicode代码点)。@Stephen只要服务器发送UTF-8(这不是您可以控制的,甚至不是您可以检查的),您现在拥有的就可以工作。但是,如果您使用
解码内容
并以
:encoding(UTF-8)
的形式打开输出,则无论服务器使用何种编码,它都会工作(只要它在标题中正确地播发,这一点到目前为止是99%正确的)。@JimGarrison
解码
并不关心您的“本地字符集”是什么。它不会丢失数据。它解码成一种表示法,其中包括Unicode中的所有内容,然后再加上一点,以便更好地度量,而不是系统语言环境。编码为缺少某些字符的编码是一个问题,但这当然是一个问题。如果你的目标是UTF-8,这也不是问题。