UTF-8 문자열을 사용하여 PHP에서 파일 시스템 기능을 어떻게 사용합니까?
-
20-09-2019 - |
문제
나는 사용할 수 없다 mkdir
UTF-8 문자로 폴더를 만들려면 :
<?php
$dir_name = "Depósito";
mkdir($dir_name);
?>
Windows 탐색기 에서이 폴더를 탐색하면 폴더 이름이 다음과 같습니다.
Depósito
어떻게해야합니까?
PHP5를 사용하고 있습니다
해결책
단지 urlencode
문자열은 파일 이름으로 원하는 것입니다. 모두 캐릭터가 돌아 왔습니다 urlencode
파일 이름 (NTFS/HFS/UNIX)에서 유효합니다. 그러면 urldecode
파일 이름은 UTF-8 (또는 인코딩이 무엇이든)로 돌아갑니다.
경고 (모두 아래 솔루션에도 적용) :
- URL 인코딩 후 파일 이름은 255 자 미만 (아마도 바이트)이어야합니다.
- UTF-8이 있습니다 다중 표현 많은 문자의 경우 (문자 결합 사용). UTF-8을 정상화하지 않으면 검색에 어려움이있을 수 있습니다.
glob
또는 개별 파일을 재개합니다. - 당신은 의존 할 수 없습니다
scandir
또는 알파-분류를위한 유사한 기능. 당신은해야합니다urldecode
그런 다음 파일 이름은 UTF-8 (및 Collations)을 인식하는 정렬 알고리즘을 사용합니다.
더 나쁜 솔루션
다음은 덜 매력적인 솔루션이며 더 복잡하고 더 많은 경고가 있습니다.
Windows에서 PHP 파일 시스템 래퍼는 파일/디렉토리 이름에 대해 ISO-8859-1 문자열을 기대하고 반환합니다. 이것은 두 가지 선택을 제공합니다.
파일 이름에서 UTF-8을 자유롭게 사용하지만 ASCII가 아닌 문자가 잘못된 것 같습니다 PHP 외부. 비 ASCII UTF-8 char는 다중로 저장됩니다 하나의 ISO-8859-1 문자. 예를 들어
ó
표시됩니다ó
Windows 탐색기에서.파일/디렉토리 이름을 제한하십시오 ISO-8859-1로 표현할 수있는 문자. 실제로, 당신은 당신의 UTF-8 현을 통과시킬 것입니다
utf8_decode
파일 시스템 기능에서 사용하기 전에 항목을 전달하십시오.scandir
당신에게 제공합니다utf8_encode
UTF-8에서 원래 파일 이름을 얻으려면.
경고가 풍부합니다!
- 만약에 어떠한 바이트 파일 시스템 함수 일치에 전달됩니다 유효하지 않은 Windows 파일 시스템 문자 ISO-8859-1에서는 운이 좋지 않습니다.
- 창 5월 영어 이외의 지역에서 ISO-8859-1 이외의 인코딩을 사용하십시오. 나는 그것이 일반적으로 ISO-8859-#중 하나 일 것이라고 생각하지만 이것은 당신이 사용해야한다는 것을 의미합니다.
mb_convert_encoding
대신에utf8_decode
.
이 악몽은 아마도 당신이 아마도 그냥 해야하는 이유입니다 바꾸어 쓰다 파일 이름을 작성합니다.
다른 팁
Unix 및 Linux (및 OS X에서도) 아래에서 현재 파일 시스템 인코딩은 LC_CTYPE
로케일 매개 변수 (기능 참조 setlocale()
). 예를 들어, 같은 것으로 평가할 수 있습니다 en_US.UTF-8
즉, 인코딩이 UTF-8임을 의미합니다. 그런 다음 파일 이름과 경로는 fopen()
또는 검색 dir()
이 인코딩으로.
Windows에서 PHP는 "비 유니 코드 인식 프로그램"으로 작동하며 파일 이름은 파일 시스템 (Windows 2000 이상)에서 사용하는 UTF-16에서 선택한 "코드 페이지"로 전환됩니다. 제어판 "지역 및 언어 옵션", 탭 패널 "형식"은 LC_CTYPE
옵션, "비공개 프로그램의 관리 -> 언어"는 파일 이름의 번역 코드 페이지를 설정합니다. 서구 국가에서 LC_CTYPE
매개 변수는 같은 것으로 평가됩니다 language_country.1252
여기서 1252는 코드 페이지이며, "Windows-1252 인코딩"이라고도하는 코드 페이지입니다. 일본에서는 932 코드 페이지가 일반적으로 다른 국가에서 설정됩니다. PHP에서는 현재 코드 페이지로 이름을 표현할 수있는 파일을 만들 수 있습니다. 반대로 파일 시스템에서 검색된 파일 이름 및 경로는 UTF-16에서 바이트로 변환됩니다. "가장 적합한"현재 코드 페이지.
이 매핑은 근사하므로 일부 문자는 예측할 수없는 방식으로 엉망이 될 수 있습니다. 예를 들어, Caffé Brillì.txt
반환됩니다 dir()
PHP 문자열로 Caff\xE9 Brill\xEC.txt
현재 코드 페이지가 1252 인 경우 예상대로, 대략적인 것을 반환합니다. Caffe Brilli.txt
일본 시스템에서는 932 코드 페이지에서 악센트 모음이 누락 된 다음 "가장 적합한"모음이 아닌 모음으로 교체 되었기 때문입니다. 전혀 번역 할 수없는 문자는 다음과 같이 검색됩니다. ?
(물음표). 일반적으로 창문 아래에는 그러한 유물을 감지 할 수있는 안전한 방법이 없습니다.
자세한 내용은 내 답장에서 확인할 수 있습니다 PHP 버그 번호. 47096.
PHP 7.1은 OEM CodePage를 무시하는 Windows의 UTF-8 파일 이름을 지원합니다.
문제는 Windows가 파일 시스템 스트링에 UTF-16을 사용하는 반면 Linux와 다른 사람들은 다른 문자 세트를 사용하지만 종종 UTF-8을 사용한다는 것입니다. UTF-8 문자열을 제공했지만 이것은 Windows에서 인코딩하는 또 다른 8 비트 문자 세트, 아마도 Latin-1 및 UTF-8에서 2 바이트로 인코딩 된 비 ASCII 문자로 해석됩니다. Windows에서 2자인 경우.
일반적인 솔루션은 소스 코드를 ASCII에서 100% 유지하고 다른 곳에 문자열을 갖는 것입니다.
사용 com_dotnet
PHP 확장, Windows '에 액세스 할 수 있습니다. Scripting.FileSystemObject
, 그런 다음 UTF-8 파일/폴더 이름으로 원하는 모든 것을 수행하십시오.
이것을 PHP 스트림 래퍼로 포장 했으므로 사용하기가 매우 쉽습니다.
먼저 그것을 확인하십시오 com_dotnet
확장자가 활성화되어 있습니다 php.ini
그런 다음 래퍼를 사용하여 다음을 활성화합니다.
stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');
마지막으로, 당신이 사용하는 기능 (mkdir, fopen, ename 등)을 사용하지만 경로를 접두사하십시오. win://
예를 들어:
<?php
$dir_name = "Depósito";
mkdir('win://' . $dir_name );
?>
이 확장을 사용하여 문제를 해결할 수 있습니다. https://github.com/kenjiuno/php-wfio
$file = fopen("wfio://多国語.txt", "rb"); // in UTF-8
....
fclose($file);
Codeigniter 텍스트 도우미를 사용해보십시오 이 링크convert_accented_characters () 함수에 대해 읽으십시오. 의상을 입을 수 있습니다.
Windows에서 UTF-8과 함께 파일 시스템을 사용하는 도구 세트 또는 리눅스를 통해 PHP
그리고 호환 가능 .htaccess
확인 파일이 존재합니다.
function define_cur_os(){
//$cur_os=strtolower(php_uname());
$cur_os=strtolower(PHP_OS);
if(substr($cur_os, 0, 3) === 'win'){
$cur_os='windows';
}
define('CUR_OS',$cur_os);
}
function filesystem_encode($file_name=''){
$file_name=urldecode($file_name);
if(CUR_OS=='windows'){
$file_name=iconv("UTF-8", "ISO-8859-1//TRANSLIT", $file_name);
}
return $file_name;
}
function custom_mkdir($dir_path='', $chmod=0755){
$dir_path=filesystem_encode($dir_path);
if(!is_dir($dir_path)){
if(!mkdir($dir_path, $chmod, true)){
//handle mkdir error
}
}
return $dir_path;
}
function custom_fopen($dir_path='', $file_name='', $mode='w'){
if($dir_path!='' && $file_name!=''){
$dir_path=custom_mkdir($dir_path);
$file_name=filesystem_encode($file_name);
return fopen($dir_path.$file_name, $mode);
}
return false;
}
function custom_file_exists($file_path=''){
$file_path=filesystem_encode($file_path);
return file_exists($file_path);
}
function custom_file_get_contents($file_path=''){
$file_path=filesystem_encode($file_path);
return file_get_contents($file_path);
}
추가 리소스
많이 쓸 필요가없고 잘 작동합니다.
<?php
$dir_name = mb_convert_encoding("Depósito", "ISO-8859-1", "UTF-8");
mkdir($dir_name);
?>