【发布时间】:2011-09-17 23:01:00
【问题描述】:
我有一大段生产代码,它可以工作。但是在我在虚拟机中设置了一个新环境后,我遇到了一个问题——每次我需要上传一个二进制文件时,它都会被 unicode 转换弄乱。
所以有一个子,问题是:
sub save_uploaded_file
{
# $file is obtained by param(zip)
my ($file) = @_;
my ($fh, $fname) = tmpnam;
my ($br, $buffer);
# commenting out next 2 lines doesn't help either
binmode $file, ':raw';
binmode $fh, ':raw';
while ($br = sysread($file, $buffer, 16384))
{
syswrite($fh, $buffer, $br);
}
close $fh;
return $fname;
}
它用于上传 zip 档案,但它们被上传为格式错误(它们的大小总是比原始文件大),我用十六进制编辑器查看了它们的内部,发现有很多 unicode 替换字符,用 utf-8 编码, 内 (EF BF BD)。
我发现读取的总字节数大于原始文件。所以问题从 sysread 开始。
文本文件上传良好。
更新: 传输文件的前几个字节有二进制表示:
0000000: 504b 0304 1400 0000 0800 efbf bd1c efbf PK..............
0000010: bd3e efbf bd1d 3aef bfbd efbf bd02 0000 .>....:.........
0000020: efbf bd05 0000 0500 1c00 422e 786d 6c55 ..........B.xmlU
0000030: 5409 0003 5cef bfbd efbf bd4d 18ef bfbd T...\......M....
0000040: efbf bd4d 7578 0b00 0104 efbf bd03 0000 ...Mux..........
0000050: 0404 0000 00ef bfbd efbf bdef bfbd 6bef ..............k.
还有原来的:
0000000: 504b 0304 1400 0000 0800 b81c d33e df1d PK...........>..
0000010: 3aa0 8102 0000 a405 0000 0500 1c00 422e :.............B.
0000020: 786d 6c55 5409 0003 5cd4 fc4d 18c7 fc4d xmlUT...\..M...M
0000030: 7578 0b00 0104 e803 0000 0404 0000 008d ux..............
0000040: 94df 6bdb 3010 c7df 03f9 1f0e e1bd 254e ..k.0.........%N
0000050: ec74 6c85 d825 2bac 9442 379a c25e ca8a .tl..%+..B7..^..
更新2 运行软件为centos 5.6、perl 5.8.8、apache 2.2.3
【问题讨论】:
-
Nitpick,文件中没有 Unicode 字符之类的东西,Unicode 必须经过编码才能存在于文件中。常见的编码有 UTF-16、UTF-8 等。听起来你有 UTF-8 字符。
-
感谢您的注意,我编辑了问题
-
你的文本文件的编码是什么?
-
zip 中的文件以 CP1251 编码(这无关紧要,因为 zip 文件本身是二进制的)。脚本源文件采用 koi8-r 编码。
标签: perl unicode binary cgi mod-perl