难倒:PHP的fopen在5.3.1 / WIN中的十六进制字符上失败了

时间:2011-02-25 05:22:56

标签: php encoding utf-8 character fopen

我尝试将iTunes网址解码为文件系统名称时遇到意外的问题。 Itunes为我提供了以下位置,用于测试UTF8兼容性的文件名。

文件://本地主机/ C:/用户/用户/桌面/%E6%9D%BF%C3%AD%E9%87%8E%E5%8F%8B%E7%BE%8E%D0%B8 %C3%B0%D0%B9%C3%BC%C3%B6 +%CF%88%E6%BC%A2%E8%AA%9E%E7%AE%80%D8%B1%D7%91%D6%B5 %D6%BC%D7%99%D8%A8%D9%8A.mp3

原始文件名是字母和字符的组合:板野野友美иðйüö+ψ汉语简رבֵּיبي.mp3

我已将其转换为php的字符串格式并删除了文件:// loaclhost / prefix: $ filename =“C:/ Users / user / Desktop / \ xE6 \ x9D \ xBF \ xC3 \ xAD \ xE9 \ x87 \ x8E \ xE5 \ x8F \ x8B \ xE7 \ xBE \ x8E \ xD0 \ xB8 \ xC3 \ xB0 \ XD0 \ xB9 \ XC3 \ XBC \ XC3 \ XB6 + \ XCF \ X88 \ XE6 \ XBC \ XA2 \ xE8 \ XAA \ x9E \ XE7 \ XAE \ X80 \ XD8 \ XB1 \ XD7 \ X91 \ XD6 \ XB5 \ XD6 \ XBC \ XD7 \ X99 \ XD8 \ xA8 \ xD9 \ x8A.mp3"

当我尝试fopen($ filename,'r'); Windows抱怨该文件不存在。

这是在Windows上的PHP5.3.1(XAMPP)上。

2 个答案:

答案 0 :(得分:0)

+,除非转义,否则表示网址中的空格。因此,Windows正确地说明该文件不存在,因为它包含空格而不是+

为什么不使用PHP提供的已建立的urldecode(),而不是尝试自己解码URL?

$iTunesURI = 'file://localhost/C:/Users/user/Desktop/%E6%9D%BF%C3%AD%E9%87%8E%E5%8F%8B%E7%BE%8E%D0%B8%C3%B0%D0%B9%C3%BC%C3%B6+%CF%88%E6%BC%A2%E8%AA%9E%E7%AE%80%D8%B1%D7%91%D6%B5%D6%BC%D7%99%D8%A8%D9%8A.mp3';
$iTunesPath = ltrim(parse_url($iTunesURI, PHP_URL_PATH), '/');

$filename = urldecode($iTunesPath);

答案 1 :(得分:0)

我现在没有带有PHP的Windows框来测试,但我认为你的问题可能是filename encoding in Windows is normally UTF-16。 Undex Linux,使用ext3文件系统,我创建了你指定的文件名,然后编写了以下PHP文件(以UTF-8编码):

<?php
$filename = "板í野友美иðйüö+ψ漢語简رבֵּיبي.mp3";
$fh = fopen($filename, 'r');
$contents = fread($fh, filesize($filename));
print $contents;
var_dump($filename);
fclose($fh);

function encode_filename($fname) {

    $replaced_filename =
        preg_replace_callback(
            '/[^\x20-\x7F]/',
            create_function(
                '$matches',
                'return "\x" . dechex(ord($matches[0]));'
            ),
            $fname
        );
    return $replaced_filename;

}

print "Encoded UTF-8 filename: " . encode_filename($filename) . "\n";

$filename = mb_convert_encoding($filename, "UTF-8", "UTF-16");
print "Encoded UTF-16 filename: " . encode_filename($filename) . "\n";

?>

它成功读取了我的目标文件并输出了其内容。

编码文件名的输出为:

Encoded UTF-8 filename: \xe6\x9d\xbf\xc3\xad\xe9\x87\x8e\xe5\x8f\x8b\xe7\xbe\x8e\xd0\xb8\xc3\xb0\xd0\xb9\xc3\xbc\xc3\xb6+\xcf\x88\xe6\xbc\xa2\xe8\xaa\x9e\xe7\xae\x80\xd8\xb1\xd7\x91\xd6\xb5\xd6\xbc\xd7\x99\xd8\xa8\xd9\x8a.mp3
Encoded UTF-16 filename: \xee\x9a\x9d\xeb\xbf\x83\xea\xb7\xa9\xe8\x9e\x8e\xee\x96\x8f\xe8\xaf\xa7\xeb\xba\x8e\xed\x82\xb8\xec\x8e\xb0\xed\x82\xb9\xec\x8e\xbc\xec\x8e\xb6\xe2\xaf\x8f\xe8\xa3\xa6\xeb\xb2\xa2\xee\xa2\xaa\xe9\xbb\xa7\xea\xba\x80\xed\x9e\x91\xed\x9a\xb5\xed\x9a\xbc\xed\x9e\x99\xe2\xb9\xad\xe7\x80\xb3

这符合您的UTF-8编码,所以这似乎是正确的。尝试UTF-16编码。或者,像我一样,将文件名直接嵌入文件中,并以UTF-16编码文件。