2010-06-01 27 views
14

Tôi có một thư mục chứa nhiều tệp, nhiều tệp trong số đó có tên không phải tiếng Anh. Tôi đang sử dụng PHP trong Windows 7.cách lặp qua tên tệp không phải tiếng Anh trong PHP

Tôi muốn liệt kê tên tệp và nội dung của chúng bằng cách sử dụng PHP.

Hiện tại tôi đang sử dụng DirectoryIteratorfile_get_contents. Điều này làm việc cho tên tập tin tiếng Anh nhưng không cho tên tập tin không phải tiếng Anh (Trung Quốc). Ví dụ: Tôi có tên tệp như "एक और प्रोब्लेम. Eml", "hello 鶨 鶖 鵨 鶣 鎹 鎣 .eml".

  1. DirectoryIterator không có khả năng để có được tên tập tin sử dụng ->getFilename()
  2. file_get_contents cũng không thể mở ngay cả khi tôi cứng mã filename trong tham số của nó.

Tôi làm cách nào?

+0

Câu hỏi này xứng đáng được gắn thẻ là đã trả lời. Artefacto nỗ lực rất lớn để cung cấp thông tin chính xác. –

+0

Có. Đó là một câu trả lời tuyệt vời. – Sabya

Trả lời

4

Điều này là không thể. Đó là một hạn chế của PHP. PHP sử dụng các phiên bản multibyte của Windows API; bạn bị giới hạn bởi các ký tự mà mã của bạn có thể đại diện.

Xem this answer.

nội dung Thư mục:

 
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 

Kiểm tra tập tin nội dung:

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

tập tin thử nghiệm kết quả:

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

Debugger đầu ra:

Gọi chồng (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 

Nó thực sự là một dấu hỏi?

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

Có! Đó là nhân vật số 63.

+0

Anh ta không thể đọc và viết tên thành các byte đơn? –

+0

@ Álvaro G. Vicario Ông có thể, nhưng ông sẽ không có tên riêng. NTFS hỗ trợ tên tập tin UCS-2 thích hợp, những gì bạn mô tả là một hack. – Artefacto

+0

Giải thích của bạn không thể tốt hơn. Tôi đã học được rất nhiều hôm nay :) –

0

Do khám phá các tập tin tôi có kịch bản này:

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

này thành công sẽ tìm thấy file: 鶨 鶖 鵨 鶣 鎹 鎣 Tôi đã thử nó ở đây trên một distro Linux mặc dù ..

để đọc nó bạn sử dụng: Dòng theo dòng:

$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

Có, sự cố là Windows. – Artefacto

3

Trả lời ngắn:

Trong Windows, bạn không thể truy cập tên tệp tùy ý bằng PHP; bạn bị giới hạn ở những tên tệp có tên được trình bày với "trang mã" hiện đang được chọn (xem phần Tùy chọn ngôn ngữ và khu vực "," Định dạng "và bảng điều khiển" Quản trị "" Ngôn ngữ cho các chương trình không phải Unicode ").

trả lời dài hơn:

Windows sử dụng UTF-16 để mã hóa tập tin từ Win2000, nhưng PHP giao tiếp với các hệ thống tập tin cơ bản như là một "phi Unicode chương trình nhận thức". Điều này có nghĩa là có một "bảng trang mã" hiện tại mà tranlates từ các chuỗi PHP tới các chuỗi UTF-16 và ngược lại. Từ PHP trang mã hiện tại có thể được lấy ra bởi setlocale() theo hình thức "language_country.codepage", ví dụ:

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

nơi 1252 là bảng trang Windows đang được chọn từ bảng điều khiển; tên tệp được lấy từ hệ thống tệp được mã hóa bằng trang mã đó; tên tệp được tạo từ PHP phải được mã hóa theo trang mã đó. Mọi thứ thậm chí còn phức tạp hơn bởi thực tế là các tên tệp UTF-16 được traslated tới chuỗi PHP bằng cách sử dụng "trang mã phù hợp nhất", đó là đại diện gần đúng của các ký tự/từ thực tế, vì vậy bạn không thể tin tưởng vào tên tệp và đường dẫn truy xuất từ ​​hệ thống tệp vì chúng có thể bị xáo trộn tùy ý.

Tài liệu tham khảo:

http://en.wikipedia.org/wiki/Windows_code_page gì "trang mã Windows" đang có.

https://bugs.php.net/bug.php?id=47096 Thông tin chi tiết về vấn đề này.

Các vấn đề liên quan