web-dev-qa-db-ja.com

UTF-8文字列を使用して、PHPでファイルシステム関数を使用するにはどうすればよいですか?

mkdirを使用してUTF-8文字でフォルダーを作成することはできません。

<?php
$dir_name = "Depósito";
mkdir($dir_name);
?>

windowsエクスプローラーでこのフォルダーを参照すると、フォルダー名は次のようになります。

Depósito

私は何をすべきか?

私はphp5を使用しています

33
Acacio Nerull

ちょうど urlencode ファイル名として必要な文字列。Allから返される文字urlencodeはファイル名(NTFS/HFS/UNIX)で有効であり、ファイル名をurldecodeファイル名をUTF-8(またはそれらが含まれていたエンコーディング)に戻すことができます。

警告(すべて以下のソリューションにも適用されます):

  • URLエンコード後、ファイル名は255文字(おそらくバイト)未満でなければなりません。
  • UTF-8には 複数の表現 が多くの文字に対して(結合文字を使用して)あります。 UTF-8を正規化しないと、globで検索したり、個々のファイルを再度開いたりするときに問題が発生する可能性があります。
  • scandirまたは同様の関数を使用してアルファソートを行うことはできません。ファイル名をurldecodeしてから、UTF-8(および照合順序)を認識するソートアルゴリズムを使用する必要があります。

悪いソリューション

以下は魅力的ではないソリューションで、より複雑で、より多くの注意事項があります。

Windowsでは、PHP=ファイルシステムラッパーは、ファイル/ディレクトリ名にISO-8859-1文字列を予期して返します。これにより、2つの選択肢が得られます。

  1. ファイル名にUTF-8を自由に使用しますが、ASCII以外の文字は正しくないように見えます PHPの外部では認識されます。 ASCII以外のUTF-8文字は、複数のsingle ISO-8859-1文字として格納されます。例えば。 óは、Windowsエクスプローラではóとして表示されます。

  2. ファイル/ディレクトリ名を ISO-8859-1で表現可能な文字 に制限します。実際には、UTF-8文字列をファイルシステム関数で使用する前に utf8_decode を介して渡し、エントリ scandir を渡します utf8_encode を使用して、元のファイル名をUTF-8で取得します。

豊富な警告!

  • ファイルシステム関数に渡されたbyteがISO-8859-1の 無効なWindowsファイルシステム文字 と一致する場合は、運が悪いです。
  • Windows may英語以外のロケールでISO-8859-1以外のエンコーディングを使用します。通常はISO-8859-#の1つになると思いますが、これはmb_convert_encodingではなくutf8_decodeを使用する必要があることを意味します。

この悪夢が、ファイル名を作成するためにおそらく transliterate とすべき理由です。

23
Steve Clay

PHP 7.1は、OEMコードページに関係なく、WindowsでUTF-8ファイル名をサポートします。

8
Anatol Belski

問題は、Windowsがファイルシステム文字列にutf-16を使用しているのに対し、Linuxとその他は異なる文字セットを使用していますが、多くの場合utf-8です。 utf-8文字列を指定しましたが、これはWindowsの別の8ビット文字セットエンコーディング(おそらくLatin-1)として解釈され、utf-8で2バイトでエンコードされている非ASCII文字は次のように処理されますWindowsでは2文字でした。

通常の解決策は、ソースコードをASCIIで100%維持し、文字列を別の場所に置くことです。

7
Lars D

com_dotnet PHP拡張機能を使用して、WindowsのScripting.FileSystemObjectにアクセスし、UTF-8ファイル/フォルダー名を使用して必要なすべてを実行できます。

これをPHPストリームラッパーとしてパッケージ化したので、非常に使いやすくなっています。

https://github.com/nicolas-grekas/Patchwork-UTF8/blob/lab-windows-fs/class/Patchwork/Utf8/WinFsStreamWrapper.php

最初にcom_dotnet拡張機能がphp.iniで有効になっていることを確認してから、ラッパーを有効にします。

stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');

最後に、慣れている関数(mkdir、fopen、renameなど)を使用しますが、パスの前にwin://を付けます

例えば:

<?php
$dir_name = "Depósito";
mkdir('win://' . $dir_name );
?>
3
Nicolas Grekas

この拡張機能を使用して問題を解決できます: https://github.com/kenjiuno/php-wfio

$file = fopen("wfio://多国語.txt", "rb"); // in UTF-8
....
fclose($file);
2
Oleg

私は多くを書く必要はありません、それはうまくいきます:

<?php
$dir_name = mb_convert_encoding("Depósito", "ISO-8859-1", "UTF-8");
mkdir($dir_name);
?>
0
Yesterday

this link からCodeIgniter Textヘルパーを試してください。convert_accented_characters()関数について読んでください。

0
TomoMiha

WindowsでUTF-8を使用してファイルシステムを使用するためのツールセット[〜#〜]または[〜#〜]linux経由の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);

}

その他のリソース

0
RafaSashi