Php 为什么Windows需要对文件名进行“utf8”解码,才能使“文件内容”正常工作?

Php 为什么Windows需要对文件名进行“utf8”解码,才能使“文件内容”正常工作?,php,linux,windows,character-encoding,filesystems,Php,Linux,Windows,Character Encoding,Filesystems,如果$filename包含umlauts(ä,ö,ü)文件获取内容($filename)在我的Windows操作系统上不起作用。通过反复试验,我发现我需要执行file\u get\u contents(utf8\u decode($filename))才能让它工作 然而,当我把这个live推到我的服务器上时(我猜它是某种Linux),它又返回了一个错误,所以我删除了utf8\u解码,突然它工作得很好 作为一种解决方法(因此我不需要每次更改代码时都手动更改这段代码),我已经尝试过了 (mb_det

如果
$filename
包含umlauts(ä,ö,ü)
文件获取内容($filename)
在我的Windows操作系统上不起作用。通过反复试验,我发现我需要执行
file\u get\u contents(utf8\u decode($filename))
才能让它工作

然而,当我把这个live推到我的服务器上时(我猜它是某种Linux),它又返回了一个错误,所以我删除了
utf8\u解码
,突然它工作得很好

作为一种解决方法(因此我不需要每次更改代码时都手动更改这段代码),我已经尝试过了

(mb_detect_encoding($filename, 'UTF-8', true)) ? utf8_decode$filename) : $filename;
由于这在另一方面对同一个问题有效(与
utf8\u encode
有相同的问题),但是
$filename
在每个(服务器)环境中都是utf8编码的,所以这不起作用,因为它总是正确的

有没有办法让这两个系统都能工作?(请不要说“只是为了PHP开发而迁移到Linux”——我有Linux,但我使用Windows有很多原因)



编辑:问题也会出现在
fopen
上,接受的解决方案也会起作用。

最好的方法是检测您是否使用Windows server。 因此,您可以应用正确的命令

if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
    echo 'This is a server using Windows!';
} else {
    echo 'This is a server not using Windows!';
}

该问题适用于文件名或目录名不支持UTF-8但Linux在php 6中支持UTF-8的窗口文件系统。该问题已解决,要在当前版本的php中解决此问题,我们可以执行以下操作:

1) 窗口支持UTF-16,linux对这种Unicode没有任何问题,我们可以用这种Unicode保存所有文件名和目录名

2) urlencode编码UTF-8,这是解决此问题的另一种方法,我建议使用此方法

我写这个脚本是为了解决这个问题,测试它

 function GetExt($sFileName)//ffilter
 {
     $sExt="";
     $sTmp=$sFileName;
     while($sTmp!="")
     {
        $sTmp=strstr($sTmp,".");
        if($sTmp!="")
        {
            $sTmp=substr($sTmp,1);
            $sExt=$sTmp;
        }
     }
     return ($sExt);
 }
  function LocatePath($Path='/',$Mode="rb",$Root="",$Open=true,$IsFile=false){//make real Path and create new Directory
     switch(strtolower($Mode)){
          case 'r':
            $Read=true;
            $Write=false;
            $Create=false;
          break;
          case 'rb'://Open for reading only; place the file pointer at the beginning of the file. 
            $Read=true;
            $Write=false;
            $Create=false;
          break;
          case 'r+'://Open for reading and writing; place the file pointer at the beginning of the file.
            $Read=true;
            $Write=true;
            $Create=false;
          break;
          case 'x'://Create and open for writing only; place the file pointer at the beginning of the file. If the file already exists, the open() call will fail by returning FALSE
            $Read=false;
            $Write=true;
            $Create=false;
          break;
          case 'wb':
            $Read=false;
            $Write=true;
            $Create=true;
          break;
          case 'ab':
            $Read=false;
            $Write=true;
            $Create=true;
          break;
          case 'w'://Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it. 
            $Read=false;
            $Write=true;
            $Create=true;
          break;
          case 'w+'://Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it. 
            $Read=true;
            $Write=true;
            $Create=true;
          break;
          case 'a'://Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it. 
            $Read=false;
            $Write=true;
            $Create=true;
          break;
          case 'a+'://Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it. 
            $Read=true;
            $Write=true;
            $Create=true;
          break;
          case 'x+'://Create and open for reading and writing; otherwise it has the same behavior as 'x'. 
            $Read=true;
            $Write=true;
            $Create=true;
          break;
          case 'c'://Open the file for writing only. If the file does not exist, it is created. If it exists, it is neither truncated (as opposed to 'w'), nor the call to this function fails (as is the case with 'x'). The file pointer is positioned on the beginning of the file.
            $Read=false;
            $Write=true;
            $Create=true;
          break;
          case 'c+'://Open the file for reading and writing; otherwise it has the same behavior as 'c'. 
            $Read=true;
            $Write=true;
            $Create=true;            
     }
     $Path=str_replace("./",'/',trim($Path));
     $Path=str_replace("../",'/',$Path);
     $Path=str_replace(".../",'/',$Path);
     $Path=ltrim($Path,'/');
     if($Path==NULL or $Path=="")$Path="/";
     $DOCUMENT_ROOT=$_SERVER['DOCUMENT_ROOT'];
     $FileRoot=$DOCUMENT_ROOT."/".$Root;
     $FileRoot=str_replace("\\",'/',$FileRoot);
     $FileRoot=rtrim(str_replace('//','/',$FileRoot),'/');
     $TMkDir=0;
     $ISDir=true;
     $RelativePath=$Path;
     $Type=GetExt($FileRoot."/".$Path);
     if($Type!=""){
         $FileName=basename($FileRoot."/".$Path);
     }
     $ParentDir=dirname($Path);
     $T=urlencode($FileRoot."/".$Path);
     $T=str_replace("%3A",':',$T);
     $T=str_replace("%2F",'/',$T);
     if(is_file($T)){
         if($IsFile){
             return array("ISDir"=>false,"Handle"=>false,"Path"=>$T,'FileName'=>$FileName,"Type"=>$Type,"RelativePath"=>$RelativePath,'ParentDir'=>$ParentDir,'Read'=>$Read,'Write'=>$Write);
         }
         $Handle=fopen($T,$Mode);
         return array("ISDir"=>false,"Handle"=>$Handle,"Path"=>$T,'FileName'=>$FileName,"Type"=>$Type,"RelativePath"=>$RelativePath,'ParentDir'=>$ParentDir,'Read'=>$Read,'Write'=>$Write);
     }
     if(is_dir($T)){
         return array("ISDir"=>true,"Handle"=>NULL,"Path"=>$T,"RelativePath"=>$RelativePath,'ParentDir'=>$ParentDir,'Read'=>$Read,'Write'=>$Write);
     }
     $PathSplit=explode("/",$Path);
     if($Create==true){
         try{
            foreach($PathSplit as $PartDir){
               $TPartDir=$PartDir;
               $PartDir=urlencode($PartDir);
               $Temp=$FileRoot."/".$PartDir;
               if(!is_file($Temp) and $TPartDir!=$FileName){
                  if(!is_dir($Temp)){
                     mkdir($Temp);
                  }
               }else{
                   $ISDir=false;
                   $Temp=$FileRoot."/".$FileName;
                   $Handle=fopen($Temp,$Mode);
                   $FileRoot=$FileRoot."/".$PartDir;    
                   break;
               }
               $FileRoot=$FileRoot."/".$PartDir;    

            }
         }catch(Extension $e){
             echo ($e);
             return false;
         }
     }else{
         try{
            foreach($PathSplit as $PartDir){
               $TPartDir=$PartDir;
               $PartDir=urlencode($PartDir);
               $Temp=$FileRoot."/".$PartDir;
               if(!is_file($Temp) and $TPartDir!=$FileName){
                  if(!is_dir($Temp)){
                     return false;
                  }
               }else{
                   $ISDir=false;
                   $Handle=fopen($Temp,$Mode);
                   $FileRoot=$FileRoot."/".$PartDir;    
                   break;
               }
               $FileRoot=$FileRoot."/".$PartDir;    
            }
         }catch(Extension $e){
             echo ($e);
             return false;
         } 
     }
     if($Open!=true){//keep open Handle for User
        fclose($Handle); 
     }
     return array("ISDir"=>$ISDir,"Handle"=>$Handle,"Path"=>$FileRoot,'FileName'=>$FileName,"Type"=>$Type,"Create"=>(!$ISDir)?true:false,"RelativePath"=>$RelativePath,'ParentDir'=>$ParentDir,'Read'=>$Read,'Write'=>$Write);
 }
样本:

如果目录或文件不存在,请打开文件进行写入和读取创建它。 (一)

返回一些信息,如fopen的句柄

输出

Array
(
[ISDir] => 
[Handle] => Resource id #3
[Path] => F:/xampp/htdocs/er/ert/a%DB%8Cgf%D8%B3%D8%A8d/%DB%8C.af
[FileName] => ی.af
[Type] => af
[Create] => 1
[RelativePath] => er/ert/aیgfسبd/ی.af
[ParentDir] => er/ert/aیgfسبd
[Read] => 1
[Write] => 1
)
(二) 如果不存在,则打开文件进行读取返回false

 print_r(LocatePath('/er/ert/aیgfسبd/ی.af',"rb")); 

还有另一种与fopen相同的模式

您的最后一行非常吸引人:)不要在文件名中使用非ASCII字符。。。。它总是会引起问题。我担心,作为一个说德语的人,我有在标题中使用umlauts的习惯(这反过来又充当文件名)。不,说真的,没有解决办法吗?这个“项目”会变得非常复杂,否则(我正在写的只是一个超级简单的博客)问题出在平台操作系统上,而且没有一个干净的答案可以跨平台工作,这就是为什么我永远不会推荐它非常感谢你这个广泛的答案,但是我想这对我的小博客来说是有点过分了。而且,我不确定
LocatePath()
的意义是什么。当然,它会给你一堆信息,但它的格式不是你可以传递给我所知道的任何东西的。
 print_r(LocatePath('/er/ert/aیgfسبd/ی.af',"rb"));