2010-06-01 48 views
14

我有一個包含多個文件的目錄,其中很多文件都是非英文名稱。我在Windows 7中使用PHP。如何遍歷PHP中的非英文文件名

我想使用PHP列出文件名及其內容。

目前我使用的是DirectoryIteratorfile_get_contents。這適用於英文文件名稱,但不適用於非英文(中文)文件名稱。

例如,我有像「एकऔरप्रोब्लेम。eml」,「hello鶨鶖鶣鶣鎹鎣.eml」的文件名。

  1. DirectoryIterator是不是能夠得到使用->getFilename()
  2. file_get_contents的文件名也無法打開,即使我硬編碼在它的參數文件名。

我該怎麼辦?

+0

這個問題值得被標記爲已回答。 Artefacto非常努力地提供準確的信息。 – 2010-06-04 09:45:49

+0

是的。這是一個很好的答案。 – Sabya 2010-06-07 12:43:18

回答

4

這是不可能的。這是PHP的限制。 PHP使用Windows API的多字節版本;您僅限於您的代碼頁可以表示的字符。

請參閱this answer

目錄內容:

 
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 

測試文件的內容:

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

測試文件的結果:

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

調試器輸出:

調用堆棧(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 

這真的是一個問號嗎?

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

是的!它是#63的字符。

+0

他不能只讀寫單個字節的名字嗎? – 2010-06-01 16:10:44

+0

@ÁlvaroG. Vicario他可以,但他不會有適當的名字。 NTFS支持正確的UCS-2文件名,你所描述的是一種黑客攻擊。 – Artefacto 2010-06-01 16:42:54

+0

你的解釋不會更好。今天我學到了很多:) – 2010-06-01 16:49:10

0

確實發現了我有這個腳本文件:

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

這將成功地找到文件:鶨鶖鵨鶣鎹鎣 我想在這裏上一個Linux發行版,但..

到閱讀它使用:通過線 線:

$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

是的,問題是Windows。 – Artefacto 2010-06-01 13:19:00

3

簡短的回答:

在Windows下,你不能用PHP訪問任意文件名;您僅限於可以使用當前選定的「代碼頁」(請參閱​​區域和語言選項「,」格式「面板和」管理「選項卡面板」非Unicode程序的語言「)表示名稱的文件名。

較長的回覆:

Windows使用UTF-16,因爲Win2000的文件編碼,但PHP與底層文件系統作爲「非Unicode識別程序」通信。這意味着有一個當前的「代碼頁表」從PHP字符串轉換爲UTF-16字符串,反之亦然。從PHP當前代碼頁可以通過在形式 「language_country.codepage」 的setlocale()檢索,例如:

的setlocale(LC_CTYPE,0)==> 「english_United States.1252」

其中1252是當前從控制面板中選擇的Windows代碼頁表格;使用該代碼頁對從文件系統檢索的文件名進行編碼;從PHP生成的文件名必須根據該代碼頁進行編碼。事實更加複雜的是,UTF-16文件名使用「最適合的代碼頁」被轉換爲PHP字符串,這是實際字符/詞的完美表示,因此您不能相信文件名和路徑從文件系統中檢索,因爲它們可能會被任意地破壞。

參考文獻:

http://en.wikipedia.org/wiki/Windows_code_page 什麼 「的Windows代碼頁」 是。

https://bugs.php.net/bug.php?id=47096 有關此問題的更多詳細信息。