2010-06-01 13 views
14

Ich habe ein Verzeichnis, das mehrere Dateien enthält, von denen viele einen nicht englischen Namen haben. Ich verwende PHP in Windows 7.Wie man über nicht-englische Dateinamen in PHP iteriert

Ich möchte den Dateinamen und ihre Inhalte mit PHP auflisten.

Momentan verwende ich und file_get_contents. Dies funktioniert für englische Dateinamen, jedoch nicht für nicht-englische (chinesische) Dateinamen.

Zum Beispiel habe ich Dateinamen wie "एक औऔ प्ोबोब्लेम. Eml", "Hallo 鶨 鶖 鵨 鶣 鎹 鎣 em .eml".

  1. DirectoryIterator ist nicht in der Lage die Dateinamen zu erhalten ->getFilename()
  2. file_get_contents verwenden, ist auch dann, wenn ich hart Code zu öffnen die Dateinamen in seinem Parameter nicht in der Lage.

Wie kann ich es tun?

+0

Diese Frage verdient es, als beantwortet markiert zu werden. Artefacto hat große Anstrengungen unternommen, um genaue Informationen zu liefern. –

+0

Ja. Das ist eine großartige Antwort. – Sabya

Antwort

4

Das ist nicht möglich. Es ist eine Einschränkung von PHP. PHP verwendet die Multibyte-Versionen von Windows-APIs. Sie sind auf die Zeichen beschränkt, die Ihre Codepage darstellen kann.

Siehe this answer.

Verzeichnis Inhalt:

 
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 

Testdatei Inhalt:

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

Testdatei Ergebnisse:

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

Debugger Ausgabe:

Aufrufhierarchie (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 

Ist es wirklich ein Fragezeichen?

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

Ja! Es ist Charakter # 63.

+0

Kann er nicht einfach Namen als einzelne Bytes lesen und schreiben? –

+0

@ Álvaro G. Vicario Er könnte, aber er würde keine richtigen Namen haben. NTFS unterstützt korrekte UCS-2-Dateinamen, was Sie beschreiben, ist ein Hack. – Artefacto

+0

Ihre Erklärung könnte nicht besser sein. Ich habe heute viel gelernt :) –

0

Sie die Dateien entdecken ich dieses Skript haben:

$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"; 

Dadurch wird die Datei erfolgreich finden: 鶨 鶖 鵨 鶣 鎹 鎣 Ich habe versucht, es hier auf einem Linux-Distro obwohl ..

zu lesen sie Sie verwenden: Zeile für Zeile:

$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

Ja, das Problem ist Windows. – Artefacto

3

Kurz Antwort:

Unter Windows können Sie nicht beliebige Dateinamen Zugriff mit PHP; Sie sind auf diejenigen Dateinamen beschränkt, deren Name mit der aktuell ausgewählten "Codepage" (siehe Regions- und Sprachoptionen "," Format "und" Verwaltung "in der Registerkarte" Sprache für Nicht-Unicode-Programme ") dargestellt werden kann.

Längere Antwort:

Windows verwendet UTF-16 für Dateicodierung seit Win2000, aber PHP kommuniziert mit dem zugrunde liegenden Dateisystem als "Nicht-Unicode-aware-Programm". Dies bedeutet, dass es eine aktuelle "Codepage-Tabelle" gibt, die von PHP-Zeichenfolgen zu UTF-16-Zeichenfolgen und umgekehrt übersetzt.

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

wo 1252: Von PHP kann die aktuelle Codepage von setlocale() in der Form "language_country.codepage", beispielsweise abgerufen werden ist die Windows-Codepage-Tabelle, die derzeit über das Bedienfeld ausgewählt ist; Dateinamen, die aus dem Dateisystem abgerufen werden, werden unter Verwendung dieser Codepage codiert; Aus PHP generierte Dateinamen müssen entsprechend dieser Codepage codiert sein. Noch komplizierter wird es durch die Tatsache, dass UTF-16-Dateinamen in PHP-Strings umgewandelt werden, indem die "best-fit" Codepage verwendet wird, also eine passende Repräsentation der tatsächlichen Zeichen/Wörter, so dass Sie nicht auf Dateinamen und Pfade vertrauen können aus dem Dateisystem abgerufen werden, da sie willkürlich entstellt werden können.

Referenzen:

http://en.wikipedia.org/wiki/Windows_code_page Was "Windows Codepages" sind.

https://bugs.php.net/bug.php?id=47096 Weitere Informationen zu diesem Problem.

Verwandte Themen