我有一个包含多个文件的目录,其中许多文件都有非英文名称。我在Windows 7中使用PHP。
我想使用PHP列出文件名及其内容。
目前我正在使用DirectoryIterator
和file_get_contents
。这适用于英文文件名,但不适用于非英文(中文)文件名。
例如,我有像“एकऔरप्रोब्लेम。eml”,“hello鶨鹙鵨鶣鎹蓥.eml”这样的文件名。
DirectoryIterator
无法使用->getFilename()
file_get_contents
也无法打开。我该怎么做?
答案 0 :(得分: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。
答案 1 :(得分:3)
简短回复:
在Windows下,您无法使用PHP访问任意文件名;您只能使用当前所选“代码页”表示其名称的文件名(请参阅“区域和语言选项”,“格式”面板和“管理”选项卡面板“非Unicode程序的语言”)。
更长的回复:
自Win2000以来,Windows使用UTF-16进行文件编码,但PHP与基础文件系统进行通信,作为“非Unicode感知程序”。这意味着有一个当前的“代码页表”,它从PHP字符串转换为UTF-16字符串,反之亦然。从PHP可以通过setlocale()以“language_country.codepage”的形式检索当前代码页,例如:
setlocale(LC_CTYPE,0)==&gt; “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 有关此问题的更多详细信息。
答案 2 :(得分: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
}