15

我有一个包含多个文件的目录,其中许多文件的名称都不是英文。我在 Windows 7 中使用 PHP。

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

目前我正在使用DirectoryIteratorfile_get_contents。这适用于英文文件名,但不适用于非英文(中文)文件名。

例如,我有像“एक और प्रोब्लेम.eml”、“你好鶨鹙鵨鶣鎹蓥.eml”这样的文件名。

  1. DirectoryIterator无法使用->getFilename()
  2. file_get_contents即使我在其参数中硬编码文件名,也无法打开。

我该怎么做?

4

3 回答 3

4

这是不可能的。这是PHP的限制。PHP 使用多字节版本的 Windows API;您仅限于您的代码页可以代表的字符。

看到这个答案

目录内容:

D:\Users\Cataphract\Desktop\teste2>dir
 驱动器 D 中的卷是 GRANDEDISCO
 卷序列号为 945F-DB89

 D:\Users\Cataphract\Desktop\teste2 目录

2010 年 1 月 6 日 17:16。
01-06-2010 17:16 ..
01-06-2010 17:15 0 科普特小写字母 shima 跟随 ϭ.txt
01-06-2010 17:18 86 teste.php
               2 个文件 86 字节
               2 Dir(s) 12.178.505.728 字节空闲

测试文件内容:

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

测试文件结果:

.
..
科普特小写字母 shima 跟随 ?.txt
teste.php

调试器输出:

调用堆栈(PHP 5.3.0):

> php5ts_debug.dll!readdir_r(DIR * dp=0x02f94068, dirent * entry=0x00a7e7cc, dirent * * result=0x00a7e7c0) 第 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) 第 820 行 + 0x17 字节 C
    php5ts_debug.dll!_php_stream_read(_php_stream * stream=0x02b94280, char * buf=0x02b9437c, unsigned int size=260, void * * * tsrm_ls=0x028a15c0) 第 603 行 + 0x1c 字节 C
    php5ts_debug.dll!_php_stream_readdir(_php_stream * dirstream=0x02b94280, _php_stream_dirent * ent=0x02b9437c, void * * * tsrm_ls=0x028a15c0) 第 1806 行 + 0x16 字节 C
    php5ts_debug.dll!spl_filesystem_dir_read(_spl_filesystem_object * intern=0x02b94340, void * * * tsrm_ls=0x028a15c0) 第 199 行 + 0x20 字节 C
    php5ts_debug.dll!spl_filesystem_dir_open(_spl_filesystem_object * intern=0x02b94340, char * path=0x02b957f0, void * * * tsrm_ls=0x028a15c0) 第 238 行 + 0xd 字节 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=0_028a1) + 0x11 字节 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=06802x1502)
    php5ts_debug.dll!zend_do_fcall_common_helper_SPEC(_zend_execute_data * execute_data=0x02bc0098, void * * * tsrm_ls=0x028a15c0) 第 313 行 + 0x78 字节 C
    php5ts_debug.dll!ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(_zend_execute_data * execute_data=0x02bc0098, void * * * tsrm_ls=0x028a15c0) 第 423 行 C
    php5ts_debug.dll!execute(_zend_op_array * op_array=0x02b93888, void * * * tsrm_ls=0x028a15c0) 第 104 行 + 0x11 字节 C
    php5ts_debug.dll!zend_execute_scripts(int type=8, void * * * tsrm_ls=0x028a15c0, _zval_struct * * retval=0x00000000, int file_count=3, ...) 第 1188 行 + 0x21 字节 C
    php5ts_debug.dll!php_execute_script(_zend_file_handle * primary_file=0x00a7fad4, void * * * tsrm_ls=0x028a15c0) 第 2196 行 + 0x1b 字节 C
    php.exe!main(int argc=2, char * * argv=0x028a14c0) 第 1188 行 + 0x13 字节 C
    php.exe!__tmainCRTStartup() 第 555 行 + 0x19 字节 C
    php.exe!mainCRTStartup() 第 371 行 C

真的是问号吗?

dp->文件信息
{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 "科普特小写字母 shima 跟随 ?.txt"
    cAlternateFileName: 0x02f941a0 "COPTIC~1.TXT"
dp->fileinfo.cFileName[34]
63'?

是的!是角色#63。

于 2010-06-01T13:18:20.810 回答
4

简短回复:

在 Windows 下,您无法使用 PHP 访问任意文件名;您仅限于那些名称可以用当前选择的“代码页”表示的文件名(请参阅区域和语言选项,“格式”面板和“管理”选项卡面板“非 Unicode 程序的语言”)。

更长的回复:

自 Win2000 以来,Windows 使用 UTF-16 进行文件编码,但 PHP 与底层文件系统作为“非 Unicode 感知程序”进行通信。这意味着当前有一个“代码页表”可以将 PHP 字符串转换为 UTF-16 字符串,反之亦然。在 PHP 中,当前代码页可以通过 setlocale() 以“language_country.codepage”的形式检索,例如:

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 有关此问题的更多详细信息。

于 2012-04-13T09:10:55.700 回答
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
}
于 2010-06-01T07:54:46.357 回答