“子程序条目中的宽字符”- UTF-8 编码的西里尔文字作为字节序列
'Wide character in subroutine entry" - UTF-8 encoded cyrillic words as sequence of bytes
我正在用一本大词典做一个 Android 文字游戏 -
单词(超过 700 000 个)作为单独的行保存在文本文件中(然后放入 SQLite 数据库中)。
为了保护我的字典,我想用 md5 对所有超过 3 个字符的单词进行编码。 (我不会用罕见的俄语字母 ъ
和 э
混淆短词和词,因为我想在我的应用程序中列出它们)。
这是我的脚本,我尝试在 Mac Yosemite:
上使用 perl v5.18.2 运行 ]
#!/usr/bin/perl -w
use strict;
use utf8;
use Digest::MD5 qw(md5_hex);
binmode(STDIN, ":utf8");
#binmode(STDOUT, ":raw");
binmode(STDOUT, ":utf8");
while(<>) {
chomp;
next if length($_) < 2; # ignore 1 letter junk
next if /жы/; # impossible combination in Russian
next if /шы/; # impossible combination in Russian
s/ё/е/g;
if (length($_) <= 3 || /ъ/ || /э/) { # do not obfuscate short words
print "$_\n"; # and words with rare letters
next;
}
print md5_hex($_) . "\n"; # this line crashes
}
如您所见,我必须在 Perl 脚本的源代码中使用西里尔字母 - 这就是我将 use utf8;
放在其顶部的原因。
但是我真正的问题是 length($_)
报告的值太高(可能报告的是字节数而不是字符数)。
所以我尝试添加:
binmode(STDOUT, ":raw");
或:
binmode(STDOUT, ":utf8");
但是脚本随后在 print md5_hex($_)
.
行处以 Wide character in subroutine entry 结束
请帮助我修复我的脚本。
我运行它是:
perl ./generate-md5.pl < words.txt > encoded.txt
为了方便起见,这里是示例 words.txt 数据:
а
аб
абв
абвг
абвгд
съемка
md5_hex
需要一个字节字符串作为输入,但您传递的是一个解码字符串(一串 Unicode 代码点)。显式编码字符串。
use strict;
use utf8;
use Digest::MD5;
use Encode;
# ....
# $_ is assumed to be utf8 encoded without check
print Digest::MD5::md5_hex(Encode::encode_utf8($_)),"\n";
# Conversion only when required:
print Digest::MD5::md5_hex(utf8::is_utf8($_) ? Encode::encode_utf8($_) : $_),"\n";
my real problem is that length($_) reports too high values
是的,您正在从 ARGV
文件句柄中读取并且尚未将其编码设置为 UTF-8
您可以使用 open
pragma 来解决这个问题。使用
而不是所有 binmode
语句
use open qw/ :std :encoding(utf8) /;
这会将所有文件句柄(包括标准文件句柄)的默认打开模式更改为 :encoding(utf8)
如果你使用 Mojolicious 然后将 to_json 替换为 encode_json 将解决问题。
来自 JSON 模块的文档,to_json 关键字:
如果您想编写与外部世界通信的现代 perl 代码,您应该使用 encode_json(假设 JSON 数据以 UTF-8 编码)。
而且我无法预见那里的非 UTF-8 世界。
如果您使用的是 perl 5.0 及更高版本,则可以通过将 to_json 更改为 encode_json
来解决此问题
我正在用一本大词典做一个 Android 文字游戏 -
单词(超过 700 000 个)作为单独的行保存在文本文件中(然后放入 SQLite 数据库中)。
为了保护我的字典,我想用 md5 对所有超过 3 个字符的单词进行编码。 (我不会用罕见的俄语字母 ъ
和 э
混淆短词和词,因为我想在我的应用程序中列出它们)。
这是我的脚本,我尝试在 Mac Yosemite:
上使用 perl v5.18.2 运行 ]#!/usr/bin/perl -w
use strict;
use utf8;
use Digest::MD5 qw(md5_hex);
binmode(STDIN, ":utf8");
#binmode(STDOUT, ":raw");
binmode(STDOUT, ":utf8");
while(<>) {
chomp;
next if length($_) < 2; # ignore 1 letter junk
next if /жы/; # impossible combination in Russian
next if /шы/; # impossible combination in Russian
s/ё/е/g;
if (length($_) <= 3 || /ъ/ || /э/) { # do not obfuscate short words
print "$_\n"; # and words with rare letters
next;
}
print md5_hex($_) . "\n"; # this line crashes
}
如您所见,我必须在 Perl 脚本的源代码中使用西里尔字母 - 这就是我将 use utf8;
放在其顶部的原因。
但是我真正的问题是 length($_)
报告的值太高(可能报告的是字节数而不是字符数)。
所以我尝试添加:
binmode(STDOUT, ":raw");
或:
binmode(STDOUT, ":utf8");
但是脚本随后在 print md5_hex($_)
.
请帮助我修复我的脚本。
我运行它是:
perl ./generate-md5.pl < words.txt > encoded.txt
为了方便起见,这里是示例 words.txt 数据:
а
аб
абв
абвг
абвгд
съемка
md5_hex
需要一个字节字符串作为输入,但您传递的是一个解码字符串(一串 Unicode 代码点)。显式编码字符串。
use strict;
use utf8;
use Digest::MD5;
use Encode;
# ....
# $_ is assumed to be utf8 encoded without check
print Digest::MD5::md5_hex(Encode::encode_utf8($_)),"\n";
# Conversion only when required:
print Digest::MD5::md5_hex(utf8::is_utf8($_) ? Encode::encode_utf8($_) : $_),"\n";
my real problem is that length($_) reports too high values
是的,您正在从 ARGV
文件句柄中读取并且尚未将其编码设置为 UTF-8
您可以使用 open
pragma 来解决这个问题。使用
binmode
语句
use open qw/ :std :encoding(utf8) /;
这会将所有文件句柄(包括标准文件句柄)的默认打开模式更改为 :encoding(utf8)
如果你使用 Mojolicious 然后将 to_json 替换为 encode_json 将解决问题。
来自 JSON 模块的文档,to_json 关键字: 如果您想编写与外部世界通信的现代 perl 代码,您应该使用 encode_json(假设 JSON 数据以 UTF-8 编码)。 而且我无法预见那里的非 UTF-8 世界。
如果您使用的是 perl 5.0 及更高版本,则可以通过将 to_json 更改为 encode_json
来解决此问题