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

难倒的:PHP';s fopen在5.3.1/WIN中的十六进制字符上失败,php,encoding,utf-8,character,fopen,Php,Encoding,Utf 8,Character,Fopen,在尝试将iTunes URL解码为文件系统名称时,php遇到了一个意想不到的问题。Itunes为测试UTF8兼容性而精心设计的文件名提供了以下位置 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%

在尝试将iTunes URL解码为文件系统名称时,php遇到了一个意想不到的问题。Itunes为测试UTF8兼容性而精心设计的文件名提供了以下位置

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

原始文件名是字母和字符的混合:板í野友美иðйüö+ψ漢語简בֵּיبي。mp3

我已将其转换为php的字符串格式,并剥离了file://loaclhost/ 前缀: $filename=“C:/Users/user/Desktop/\xE6\xC3\xAD\xE9\x87\x8E\xE5\x8F\x8B\xE7\xBE\x8E\xD0\xB8\xC3\xB0\xD0\xB9\xC3\xBC\xC3\xc6+\xCF\x88\xE6\xBC\xA2\xE8\xAA\x9E\xE7\xAE\x80\xD8\xB1\xD7\xd1\xD7\x91\xD6\xB6\xB6\xBC\xb7\xD8\xD8\xD8

当我试图打开($filename,'r');windows抱怨该文件不存在


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

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

与其自己尝试解码URL,为什么不使用PHP提供的已建立的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);

我现在没有一个带有PHP的Windows盒子可以测试,但是我认为你的问题很可能是这个。使用ext3文件系统,我创建了您指定的文件名,然后编写了以下PHP文件(以UTF-8编码):


这与您的UTF-8编码相匹配,因此这似乎是正确的。尝试UTF-16编码。或者,像我做的那样,直接将文件名嵌入文件中,并用UTF-16对文件进行编码。

感谢您的回复和其他清理iTunes URL的方法。不幸的是,这不是问题所在。。我已经尝试过用十六进制字符替换“+”,并尝试过urldecode和rawurldecode,但我还没有找到任何方法来获得一个看起来合法的文件名,以便读取更长的字节长度。我有一种感觉,php在这个版本的XAMPP中可能没有正确编译。感谢所有的背景知识。虽然向上采样到UTF16并没有起到作用,但我认为您发布的文章可能是关于php为较新的windows FS API编译错误的内容,OSX和ubuntu上的这个单元测试是绿色的,因此我认为一旦进入多字节unicode,文件系统通信就会出现问题。
<?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