Почему Windows должна поддерживать имена файлов `utf8_decode` для` file_get_contents`?

Если $filename содержит umlauts (ä, ö, ü) file_get_contents($filename) , не работает в моей ОС Windows. В результате проб и ошибок я выяснил, что мне нужно сделать file_get_contents(utf8_decode($filename)) чтобы заставить его работать.

Однако, когда я нажал этот live на свой сервер (предположим, что это какой-то Linux), он снова вернулся к ошибке, поэтому я удалил utf8_decode и внезапно работал отлично.

В качестве обходного пути (так что мне не нужно менять этот кусок кода вручную каждый раз, когда я вношу изменения в код), я уже пробовал

 (mb_detect_encoding($filename, 'UTF-8', true)) ? utf8_decode$filename) : $filename; 

так как это уже работало для одной и той же проблемы в обратном направлении (имело ту же проблему с utf8_encode ), но $filename оказался кодировкой UTF8 в каждой (серверной) среде, поэтому это не работает, так как это всегда так.

Любые идеи, как заставить это работать в обеих системах? (Пожалуйста, «просто переходите на Linux для разработки PHP» – у меня есть Linux, но ATM я использую Windows по ряду причин)


Изменить: проблема появляется также с fopen и принятое решение работает.

Solutions Collecting From Web of "Почему Windows должна поддерживать имена файлов `utf8_decode` для` file_get_contents`?"

Лучшим способом было бы определить, используется ли ваш сервер Windows или нет. Из этого вы можете применить правильную команду

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

проблема заключается в файловой системе Windows, которая не поддерживает UTF-8 для имени файла или имени dir, но Linux поддерживает UTF-8 в php 6, эта проблема решена, для решения этой проблемы в текущей версии 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); } в  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); } 

образец:

открыть файл для записи и чтения, если каталог или файл не существует, создайте его. 1)

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

вернуть некоторую информацию, такую ​​как ручка 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 ) 

2) открыть файл для чтения, если не существует return false

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

и какой-то другой режим, такой же, как fopen