PHP İngilizce olmayan dosya adları üzerinde yineleme nasıl

4 Cevap php

Ben İngilizce olmayan bir adı vardır, birçoğu birkaç dosya içeren bir dizin var. Windows 7'de PHP kullanıyorum.

Ben PHP kullanarak dosya ve içeriğini listelemek istiyorum.

Şu anda DirectoryIterator ve file_get_contents kullanıyorum. Bu ancak İngilizce olmayan (çince) dosya adları için İngilizce dosya adları için çalışıyor.

Örneğin, ben "एक और प्रोब्लेम. Eml", "merhaba 鶨 鹙 鵨 鶣 鎹 蓥. Eml" gibi dosya adları vardır.

  1. DirectoryIterator kullanarak dosya almak mümkün değil ->getFilename()
  2. file_get_contents de açmak mümkün değil ben bile zor kod parametresi olarak dosya halinde.

Ben bunu nasıl yapabilirim?

4 Cevap

Bu, mümkün değildir. Bu PHP bir sınırlama var. PHP, Windows API'leri Çokbaytlı sürümlerini kullanır; Eğer kod sayfası temsil edebilir karakterle sınırlıdır ediyoruz.

Bkz this answer.

Dizin içeriği:

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

Test dosyası içeriği:

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

Test dosyası sonuçları:

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

Debugger çıkışı:

Yığınını (PHP 5.3.0) Çağrı:

>   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

Bir soru işareti gerçekten var mı?

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

Evet! Bu karakter 63. bulunuyor.

Sen başarısız konusunda çok az ayrıntı vermek ama, benim deneyim, PHP uluslararası dosya adları ile temel sorun kodunuzu ve dosya sisteminin farklı karakter kümelerini kullanarak gelir. NTFS UTF-16 kullanır inanıyorum. Script kodlanmış ise, örneğin, UTF-8, sabit-kod dosyalanmaları yüzden UTF-8 kodlaması kullanıyor olmayan bir İngilizce adı bulunan olmayacaktır.

Sen iconv() adlarını çevirmek için kullanabilirsiniz.

Edit

Unicode metin editörleri de dahil olmak üzere çoğu uygulamalar tarafından sınırlı olması nedeniyle destek test etmek zor olabilir. : Ben bu test senaryosunu yazdı ve Firefox ile test böylece tarayıcılar oldukça iyi yapmak

<?php /* Save as UTF-8 without BOM (€ÁÑ) */

header('Content-Type: text/html; charset=utf-8');

if( isset($_POST['filename']) ){
    touch($_POST['filename']);
}

?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head><title></title>
</head>
<body>

<form action="" method="post">
<input type="text" name="filename" size="50">
<input type="submit" value="Create file">
</form>

<?php

echo '<ul>';
foreach(glob('*') as $i){
    echo '<li>' . htmlspecialchars($i) . '</li>';
}
echo '</ul>';

?>

</body>
</html>

Ardından, http://www.lorem-ipsum.info/ egzotik dillerde bazı dizeleri almak için kullanabilirsiniz. Benim sistemi (Windows XP) kod sayfası Win-1252 (Doğu Avrupa) kullanıyor ama bu gerçeği "知 是 指. Txt" gibi dosyaları oluşturma ve okuma PHP engellemez. Tabii ki, Windows explorer çöp görüntüler.

Kısa cevap:

Windows altında PHP ile keyfi dosya adlarını erişemiyor; Eğer Adını seçili "kod sayfası" ile temsil edilebilir (Bölge ve Dil Seçenekleri bölümüne bakın "," Format "paneli ve" İdari "sekmesi paneli" Dil Unicode olmayan programlar için ") bu dosya adları ile sınırlıdır.

Daha uzun cevap:

, Windows Win2000 beri dosya kodlama UTF-16 kullanır, ancak PHP bir "non-Unicode farkında programı" olarak altta yatan dosya sistemi ile iletişim kurmak. Bu PHP dizeleri UTF-16 dizeleri ve tersi için tranlates bir akım "kod sayfası tablosu" var demektir. PHP Geçerli kod sayfası, örneğin, formu "language_country.codepage" in setlocale () tarafından alınabilir:

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

1252 şu anda kontrol panelinden seçilen Windows kod sayfa tablosu olduğu; dosya sisteminden alınan dosya adları bu kod sayfasını kullanılarak kodlanmıştır; PHP oluşturulan dosya isimleri bu kod sayfasına göre kodlanmış olmalıdır. Dosya adları ve yolları üzerinde güvenmiyorum böylece işler daha da karmaşık UTF-16 dosya adları "en uygun kod sayfası" PHP kullanarak dizelere traslated olduğu gerçeği ile vardır ki, gerçek karakterler / kelimelerin bir approxymated temsilidir bunlar keyfi karıştırılmış olabileceği gibi dosya sistemi alınır.

Referanslar:

http://en.wikipedia.org/wiki/Windows_code_page What "Windows code pages" are.

https://bugs.php.net/bug.php?id=47096 More details about this issue.

Ben bu script var dosyaları keşfetmek yapın:

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

This will succesfully find the file: 鶨鶖鵨鶣鎹鎣 I tried it here on a Linux distro though..

to read it you use: Line by line:

$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
}