2010-06-01 33 views
14

J'ai un répertoire qui contient plusieurs fichiers, dont beaucoup ont un nom non-anglais. J'utilise PHP dans Windows 7.comment itérer sur des noms de fichiers non-anglais en PHP

Je veux lister le nom de fichier et leur contenu en utilisant PHP. Actuellement, j'utilise DirectoryIterator et file_get_contents. Cela fonctionne pour les noms de fichiers en anglais, mais pas pour les noms de fichiers non anglais (chinois). Par exemple, j'ai des noms de fichiers comme "एक और प्रोब्लेम. Eml", "bonjour 鶨 鶖 鵨 鶣 鎹 鎣 .eml".

  1. DirectoryIterator n'est pas en mesure d'obtenir le nom du fichier en utilisant ->getFilename()
  2. file_get_contents est pas non plus en mesure d'ouvrir même si je coder en dur le nom du fichier dans son paramètre.

Comment puis-je le faire?

+0

Cette question mérite d'être signalée comme ayant été répondue. Artefacto a fait de gros efforts pour fournir des informations précises. –

+0

Oui. Thats une bonne réponse. – Sabya

Répondre

4

Ce n'est pas possible. C'est une limitation de PHP. PHP utilise les versions multi-octets des API Windows; vous êtes limité aux caractères que votre page de codes peut représenter.

Voir this answer.

contenu Directory:

 
D:\Users\Cataphract\Desktop\teste2>dir 
Volume in drive D is GRANDEDISCO 
Volume Serial Number is 945F-DB89 

Directory of D:\Users\Cataphract\Desktop\teste2 

01-06-2010 17:16    . 
01-06-2010 17:16    .. 
01-06-2010 17:15     0 coptic small letter shima follows ϭ.txt 
01-06-2010 17:18    86 teste.php 
       2 File(s)    86 bytes 
       2 Dir(s) 12.178.505.728 bytes free 

contenu du fichier de test:

<?php 
exec('pause'); 
foreach (new DirectoryIterator(".") as $v) { 
    echo $v."\n"; 
} 

résultats fichier test:

 
. 
.. 
coptic small letter shima follows ?.txt 
teste.php 

sortie Debugger:

pile d'appels (PHP 5.3.0):

 
> php5ts_debug.dll!readdir_r(DIR * dp=0x02f94068, dirent * entry=0x00a7e7cc, dirent * * result=0x00a7e7c0) Line 80 C 
    php5ts_debug.dll!php_plain_files_dirstream_read(_php_stream * stream=0x02b94280, char * buf=0x02b9437c, unsigned int count=260, void * * * tsrm_ls=0x028a15c0) Line 820 + 0x17 bytes C 
    php5ts_debug.dll!_php_stream_read(_php_stream * stream=0x02b94280, char * buf=0x02b9437c, unsigned int size=260, void * * * tsrm_ls=0x028a15c0) Line 603 + 0x1c bytes C 
    php5ts_debug.dll!_php_stream_readdir(_php_stream * dirstream=0x02b94280, _php_stream_dirent * ent=0x02b9437c, void * * * tsrm_ls=0x028a15c0) Line 1806 + 0x16 bytes C 
    php5ts_debug.dll!spl_filesystem_dir_read(_spl_filesystem_object * intern=0x02b94340, void * * * tsrm_ls=0x028a15c0) Line 199 + 0x20 bytes C 
    php5ts_debug.dll!spl_filesystem_dir_open(_spl_filesystem_object * intern=0x02b94340, char * path=0x02b957f0, void * * * tsrm_ls=0x028a15c0) Line 238 + 0xd bytes C 
    php5ts_debug.dll!spl_filesystem_object_construct(int ht=1, _zval_struct * return_value=0x02b91f88, _zval_struct * * return_value_ptr=0x00000000, _zval_struct * this_ptr=0x02b92028, int return_value_used=0, void * * * tsrm_ls=0x028a15c0, long ctor_flags=0) Line 645 + 0x11 bytes C 
    php5ts_debug.dll!zim_spl_DirectoryIterator___construct(int ht=1, _zval_struct * return_value=0x02b91f88, _zval_struct * * return_value_ptr=0x00000000, _zval_struct * this_ptr=0x02b92028, int return_value_used=0, void * * * tsrm_ls=0x028a15c0) Line 658 + 0x1f bytes C 
    php5ts_debug.dll!zend_do_fcall_common_helper_SPEC(_zend_execute_data * execute_data=0x02bc0098, void * * * tsrm_ls=0x028a15c0) Line 313 + 0x78 bytes C 
    php5ts_debug.dll!ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(_zend_execute_data * execute_data=0x02bc0098, void * * * tsrm_ls=0x028a15c0) Line 423 C 
    php5ts_debug.dll!execute(_zend_op_array * op_array=0x02b93888, void * * * tsrm_ls=0x028a15c0) Line 104 + 0x11 bytes C 
    php5ts_debug.dll!zend_execute_scripts(int type=8, void * * * tsrm_ls=0x028a15c0, _zval_struct * * retval=0x00000000, int file_count=3, ...) Line 1188 + 0x21 bytes C 
    php5ts_debug.dll!php_execute_script(_zend_file_handle * primary_file=0x00a7fad4, void * * * tsrm_ls=0x028a15c0) Line 2196 + 0x1b bytes C 
    php.exe!main(int argc=2, char * * argv=0x028a14c0) Line 1188 + 0x13 bytes C 
    php.exe!__tmainCRTStartup() Line 555 + 0x19 bytes C 
    php.exe!mainCRTStartup() Line 371 C 

Est-ce vraiment un point d'interrogation?

 
dp->fileinfo 
{dwFileAttributes=32 ftCreationTime={...} ftLastAccessTime={...} ...} 
    dwFileAttributes: 32 
    ftCreationTime: {dwLowDateTime=2784934701 dwHighDateTime=30081445 } 
    ftLastAccessTime: {dwLowDateTime=2784934701 dwHighDateTime=30081445 } 
    ftLastWriteTime: {dwLowDateTime=2784934701 dwHighDateTime=30081445 } 
    nFileSizeHigh: 0 
    nFileSizeLow: 0 
    dwReserved0: 3435973836 
    dwReserved1: 3435973836 
    cFileName: 0x02f9409c "coptic small letter shima follows ?.txt" 
    cAlternateFileName: 0x02f941a0 "COPTIC~1.TXT" 
dp->fileinfo.cFileName[34] 
63 '?' 

Oui! C'est le personnage # 63.

+0

Ne peut-il pas simplement lire et écrire des noms en octets uniques? –

+0

@ Álvaro G. Vicario Il pourrait, mais il n'aurait pas de noms propres. NTFS prend en charge les noms de fichiers UCS-2 appropriés, ce que vous décrivez est un hack. – Artefacto

+0

Votre explication ne pourrait pas être mieux. J'ai beaucoup appris aujourd'hui :) –

0

Faites découvrir les fichiers que j'ai ce script:

$content = scandir($directory); 
$list = "<select size = 5 name ='file' id='file'>\n"; 
for($i = 0; $i < count ($content); $i ++) { 
    $list .= "<option>$content[$i] </option>\n"; 
} 
$list .= "</select>\n"; 

Cela avec succès trouver le fichier: 鶨 鶖 鵨 鶣 鎹 鎣 Je l'ai essayé ici sur une distribution Linux bien ..

à lire que vous utilisez: ligne par ligne:

$lines = file('file.txt'); 
//loop through our array, show HTML source as HTML source; and line numbers too. 
foreach ($lines as $line_num => $line) { 
print "Line #<b>{$line_num}</b> : " . htmlspecialchars($line) . "<br />\n";//or try it without the htmlspecialchars 
} 
+0

Oui, le problème est Windows. – Artefacto

3

réponse courte:

Sous Windows, vous ne pouvez pas accéder aux noms de fichiers arbitraires avec PHP; vous êtes limité aux noms de fichiers dont le nom peut être représenté avec la "page de codes" actuellement sélectionnée (voir Options régionales et linguistiques "," Format "et onglet" Administration "" Langue pour les programmes non Unicode ").

réponse plus longue:

Windows utilise UTF-16 pour l'encodage de fichiers depuis Win2000, mais PHP communiquer avec le système de fichiers sous-jacent comme un "programme courant non Unicode". Cela signifie qu'il existe une "table de pages de codes" qui passe des chaînes PHP aux chaînes UTF-16 et vice-versa. A partir de la page PHP de code actuel peut être récupéré par setlocale() sous la forme "language_country.codepage", par exemple:

setlocale (LC_CTYPE, 0) ==> "english_United States.1252"

où 1252 est la table de pages de codes Windows actuellement sélectionnée dans le panneau de configuration; les noms de fichiers extraits du système de fichiers sont codés en utilisant cette page de code; les noms de fichiers générés à partir de PHP doivent être codés en fonction de cette page de code. Les choses sont encore plus compliquées du fait que les noms de fichiers UTF-16 sont traduits en chaînes PHP en utilisant la "page de codes best-fit", c'est-à-dire une représentation approximative des caractères/mots réels. récupérées du système de fichiers car elles pourraient être mutilées arbitrairement.

Références:

http://en.wikipedia.org/wiki/Windows_code_page "Qu'est-ce que les pages de code Windows" sont.

https://bugs.php.net/bug.php?id=47096 Plus d'informations sur ce problème.