2010-06-01 13 views
14

Tengo un directorio que contiene varios archivos, muchos de los cuales tienen un nombre no inglés. Estoy usando PHP en Windows 7.cómo iterar sobre nombres de archivo no ingleses en PHP

Quiero mostrar el nombre del archivo y su contenido usando PHP.

Actualmente estoy usando DirectoryIterator y file_get_contents. Esto funciona para nombres de archivos en inglés, pero no para nombres de archivos que no sean en inglés (chino).

Por ejemplo, tengo nombres de archivos como "एक पर प्रोब्लेम. Eml", "hola 鶨 ोब ोब ोब e e e e.

  1. DirectoryIterator no es capaz de obtener el nombre del archivo usando ->getFilename()
  2. file_get_contents tampoco es capaz de abrir incluso si codificar el nombre de archivo en su parámetro.

¿Cómo puedo hacerlo?

+0

Esta pregunta merece ser etiquetada como respondida. Artefacto hizo un gran esfuerzo para proporcionar información precisa. –

+0

Sí. Esa es una gran respuesta. – Sabya

Respuesta

4

Esto no es posible. Es una limitación de PHP. PHP usa las versiones multibyte de las API de Windows; está limitado a los caracteres que su página de códigos puede representar.

Ver this answer.

contenidos Directorio:

 
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 

contenido del archivo de prueba:

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

resultados de archivos de prueba:

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

depurador de salida:

pila de llamadas (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 

¿Es realmente un signo de interrogación?

 
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 '?' 

Sí! Es el personaje # 63.

+0

¿No puede simplemente leer y escribir nombres como bytes individuales? –

+0

@ Álvaro G. Vicario Él podría, pero no tendría los nombres propios. NTFS admite nombres de archivo UCS-2 adecuados, lo que usted describe es un truco. – Artefacto

+0

Tu explicación no podría ser mejor. He aprendido mucho hoy :) –

0

Haz descubrir los archivos que tengo este 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"; 

Esto con éxito encontrar el archivo: 鶨 鶖 鵨 鶣 鎹 鎣 lo probé aquí en una distribución de Linux, aunque ..

a leerlo que utilice: línea por línea:

$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

Sí, el problema es Windows. – Artefacto

3

respuesta corta:

En Windows, no se puede acceder a los nombres de archivos arbitrarios con PHP; está limitado a los nombres de archivo cuyo nombre puede representarse con la "página de códigos" seleccionada actualmente (consulte "Opciones regionales y de idioma", el panel "Formato" y el panel "Tablas administrativas" "Idioma para programas que no son Unicode").

respuesta más larga:

Windows utiliza UTF-16 para la codificación de archivos desde Win2000, pero PHP comunicarse con el sistema de archivos subyacente como un "programa cuenta no Unicode". Esto significa que hay una "tabla de páginas de códigos" actual que se traduce de cadenas PHP a cadenas UTF-16 y viceversa. A partir de PHP de la página de códigos actual puede ser recuperada por setlocale() en la forma "language_country.codepage", por ejemplo:

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

en 1252 es la tabla de página de códigos de Windows actualmente seleccionada desde el panel de control; los nombres de archivo recuperados del sistema de archivos están codificados usando esa página de códigos; los nombres de archivo generados desde PHP deben codificarse de acuerdo con esa página de códigos. Las cosas son aún más complicadas por el hecho de que los nombres de los archivos UTF-16 se trasladan a las cadenas PHP utilizando la "mejor página de códigos", que es una representación aproximada de los caracteres/palabras reales, por lo que no puede confiar en los nombres y rutas de los archivos recuperado del sistema de archivos, ya que podrían ser arbitrariamente mutilados.

Referencias:

http://en.wikipedia.org/wiki/Windows_code_page ¿Qué "páginas de códigos de Windows" son.

https://bugs.php.net/bug.php?id=47096 Más detalles sobre este tema.

Cuestiones relacionadas