如何通过Ajax或CGI获取Perl Unicode字符串输入的长度?

时间:2010-09-13 21:52:41

标签: ajax perl unicode utf-8

好的,这应该非常简单,但我已经搜索了所有答案并阅读了以下主题: How do I find the length of a Unicode string in Perl?

这对我没有帮助。我知道如何让Perl将字符串常量视为UTF-8并返回正确数量的字符(而不是字节),但是当Perl通过我的AJAX调用接收字符串时,它会以某种方式起作用。

下面,我将以unicode发布三个希腊字母Alpha,Beta和Omega。 Perl告诉我长度是6(字节),它应该告诉我只有3(字符)。如何获得正确的字符数?

#!/usr/bin/perl
use strict;

if ($ENV{CONTENT_LENGTH}) {
    binmode (STDIN, ":utf8");
    read (STDIN, $_, $ENV{CONTENT_LENGTH});
    s{%([a-fA-F0-9]{2})}{ pack ('C', hex ($1)) }eg;
    print "Content-Type: text/html; charset=UTF-8\n\nReceived: $_ (".length ($_)." chars)";
    exit;
}

print "Content-Type: text/html; charset=UTF-8\n\n";
print qq[<html><head><script>
        var oRequest;
        function MakeRequest () {
            oRequest = new XMLHttpRequest();
            oRequest.onreadystatechange = zxResponse;
            oRequest.open ('POST', '/test/unicode.cgi', true);
            oRequest.send (encodeURIComponent (document.oForm.oInput.value));
        }
        function zxResponse () {
            if (oRequest.readyState==4 && oRequest.status==200) {
                alert (oRequest.responseText);
            }
        }
    </script></head><body>
        <form name="oForm" method="POST">
            <input type="text" name="oInput" value="&#x03B1;&#x03B2;&#x03A9;">
            <input type="button" value="Ajax Submit" onClick="MakeRequest();">
        </form>
    </body></html>
];

顺便说一句,代码是内部简化的(我知道如何进行跨浏览器的AJAX调用等)并且使用CGI Perl模块不是一个选项。

3 个答案:

答案 0 :(得分:8)

在调用length之前解码此字符串。例如:

use Encode;

my $utf_string = decode_utf8($_); ## parse string to find utf8 octets
print length($utf_string);

来自encode manual

  

$ string = decode_utf8($ octets [,CHECK]);

     

相当于$ string = decode(“utf8”,$ octets [,CHECK])。由$ octets表示的八位字节序列从UTF-8解码为逻辑字符序列。并非所有八位字节序列都形成有效的UTF-8编码,因此此调用可能会失败。有关CHECK,请参阅处理格式错误的数据。

答案 1 :(得分:4)

对于完成此操作的“本机”方式,您可以在使用此方法复制时进行转换:

将内存文件中的模式设置为所需模式并从中读取。这将在读取字符时进行转换。

use strict;
use warnings;

my $utf_str = "αβΩ"; #alpha; bravo; omega

print "$utf_str is ", length $utf_str, " characters\n";

use open ':encoding(utf8)';
open my $fh, '<', \$utf_str;

my $new_str;

{ local $/; $new_str=<$fh>; }

binmode(STDOUT, ":utf8");
print "$new_str ", length $new_str, " characters"; 

#output:
αβΩ is 6 characters
αβΩ 3 characters

如果要转换编码,可以使用:

my $utf_str = "αβΩ";
print "$utf_str is ", length $utf_str, " characters\n";
binmode(STDOUT, ":utf8");
utf8::decode($utf_str);
print "$utf_str is ", length $utf_str, " characters\n";

#output:
αβΩ is 6 characters
αβΩ is 3 characters

但是你不应该回避Encode

答案 2 :(得分:2)

如果您知道字符串在utf8中,请使用utf8::decode。它是核心,没有内存使用惩罚:

基本无操作循环内存使用:

$ perl -e 'sleep 1 while 1' &
[1] 17372
$ ps u | grep 17372 | grep -v grep
okram    17372  0.0  0.1   5464  1172 pts/0    S    01:24   0:00 perl -e [...]

Encode的内存使用情况:

$ perl -MEncode -e 'sleep 1 while 1' &
[1] 17488
$ ps u | grep 17488 | grep -v grep
okram    17488  0.7  0.2   6020  2224 pts/0    S    01:27   0:00 perl [...]

建议的方式:

$ perl -e '$str="ææææ";utf8::decode $str;print length $str,"\n\n";
sleep 1 while 1' &
[1] 17554
$ 4
$ ps u | grep 17554| grep -v grep
okram    17554  0.0  0.1   5464  1176 pts/0    S    01:28   0:00 perl -e [...]

如您所见,对于该utf8字符串,utf8::decode之后的字符串长度为4,并且内存使用率与基线(1)基本相同。编码似乎消耗了更多的内存......