Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
274 views
in Technique[技术] by (71.8m points)

php - Why does Windows need to `utf8_decode` filenames for `file_get_contents` to work?

If $filename contains umlauts (?,?,ü) file_get_contents($filename) doesn't work on my Windows OS. By trial and error I found out that I need to do file_get_contents(utf8_decode($filename)) to get it to work.

However, when I pushed this live to my server (guess it's some kind of Linux) it returned an error again, so I removed the utf8_decode and suddenly it worked perfectly.

As a workaround (so I don't need to change this piece of code manually every time I make changes to the code) I already tried

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

as this already worked for the same problem the other way round (had the same problem with utf8_encode), but $filename turned out to be UTF8-encoded in every (server) environment, so this doesn't work, as it's always true.

Any ideas how to get this to work on both systems? (Please no "just migrate to Linux for PHP development"—I've got Linux, but ATM I'm using Windows for a number of reasons)


Edit: the problem appears also with fopen and the accepted solution works as well.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

the problem is for window file system that not support UTF-8 for filename or dir name but Linux support UTF-8 in php 6 this problem solved, for solve this problem in current version of php we can do some work like:

1) window support UTF-16 and linux has not any problem with this kind of Unicode we can save all file name and directory name in this Unicode

2) urlencode that encode UTF-8 ,this is one another way for solve this problem I recommended to use this .

i wrote this script for solve this problem test it.

 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);
 }

sample:

open file for write and read if directory or file not exist create it. 1)

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

return some information like handle of fopen

output

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) open file for read if not exist return false

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

and some another mode that is same of fopen


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...