34

mkdirUTF-8文字でフォルダを作成するために使用することはできません:

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

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

Depósito

私は何をすべきか?

php5を使用しています

4

9 に答える 9

25

urlencodeファイル名として必要な文字列だけ。 から返されるすべての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の外部では正しく表示されないことを理解してください。非ASCIIUTF-8文字は、複数の単一ISO-8859-1文字として格納されます。たとえば、Windowsエクスプローラのóように表示されます。ó

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

たくさんの警告!

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

この悪夢は、おそらくファイル名を作成するために音訳する必要がある理由です。

于 2009-10-25T14:28:23.653 に答える
12

UnixおよびLinux(および場合によってはOS Xでも)では、現在のファイルシステムエンコーディングはLC_CTYPEロケールパラメータによって指定されます(関数を参照setlocale())。たとえばen_US.UTF-8、エンコーディングがUTF-8であることを意味するようなものに評価される場合があります。次に、ファイル名とそのパスをこのエンコーディングで作成fopen()または取得できます。dir()

Windowsでは、PHPは「非Unicode対応プログラム」として動作し、ファイル名はファイルシステム(Windows 2000以降)で使用されるUTF-16から選択された「コードページ」に変換されます。コントロールパネルの[地域と言語のオプション]、タブパネルの[形式]は、LC_CTYPEオプションによって取得されるコードページを設定し、[管理]->[非Unicodeプログラムの言語]はファイル名の翻訳コードページを設定します。西欧諸国では、LC_CTYPEパラメータは次のように評価されますlanguage_country.1252ここで、1252はコードページであり、「Windows-1252エンコーディング」とも呼ばれ、ISO-8859-1に類似しています(ただし、完全に同じではありません)。日本では通常、932コードページが代わりに設定され、他の国では同様に設定されます。PHPでは、現在のコードページで名前を表現できるファイルを作成できます。逆に、ファイルシステムから取得されたファイル名とパスは、「最適な」現在のコードページを使用してUTF-16からバイトに変換されます。

このマッピングは概算であるため、一部の文字は予測できない方法でマングルされる可能性があります。たとえば、現在のコードページが1252の場合、期待どおりにPHP文字列としてCaffé Brillì.txt返されますが、アクセント付き母音が932コードページから欠落しているため、日本のシステムでは近似値が返され、「最適」に置き換えられます。 「アクセントのない母音。まったく翻訳できない文字は(疑問符)として取得されます。一般に、Windowsでは、このようなアーティファクトを安全に検出する方法はありません。dir()Caff\xE9 Brill\xEC.txtCaffe Brilli.txt?

詳細については、PHPのバグ番号への返信をご覧ください。47096

于 2012-04-04T00:35:57.247 に答える
9

PHP 7.1は、OEMコードページを無視して、WindowsでUTF-8ファイル名をサポートします。

于 2016-07-19T19:17:26.657 に答える
7

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

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

于 2009-10-06T14:19:33.087 に答える
3

PHP拡張機能を使用すると、 com_dotnetWindowsにアクセス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 );
?>
于 2013-11-30T10:45:59.540 に答える
3

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

$file = fopen("wfio://多国語.txt", "rb"); // in UTF-8
....
fclose($file);
于 2015-09-03T10:06:41.720 に答える
0

このリンクからCodeIgniterテキストヘルパーを試してください convert_accented_characters()関数について読んでください。

于 2012-02-20T11:42:30.323 に答える
0

チェックファイルを介してWindowsまたはLinuxで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);

}

追加のリソース

于 2014-07-23T15:59:09.530 に答える
0

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

<?php
$dir_name = mb_convert_encoding("Depósito", "ISO-8859-1", "UTF-8");
mkdir($dir_name);
?>
于 2019-01-10T09:51:06.353 に答える