2012-01-18 269 views
0

有沒有辦法在沒有BOM編碼的情況下檢查UTF-8的CSV文件?我想檢查整個文件而不是單個字符串。用PHP檢查csv文件是否採用UTF-8編碼

我會嘗試設置第一行的特殊字符,並且不會讀取字符串,並檢查它是否與我的腳本中硬編碼的字符串匹配。但我不知道這是否是一個好主意。

Google only showed me this。但是最後一篇文章中的鏈接不可用。

回答

8
if (mb_check_encoding(file_get_contents($file), 'UTF-8')) { 
    // yup, all UTF-8 
} 

你也可以通過它逐行與fgets,如果文件很大,你不想給它的所有存儲在內存中的一次。不確定你的問題的第二部分是什麼意思。

+0

此函數不檢查錯誤的字節序列,它只檢查字節流是否有效。 – Damien 2012-01-18 08:44:03

+0

@Damien如果你能澄清究竟是什麼意思,我會很感激。它捕獲畸變的UTF-8字節序列,那麼什麼是「壞字節序列」呢? http://codepad.viper-7.com/6yvKe9。 – deceze 2012-01-18 08:48:29

+0

有一個[bug報告](https://bugs.php.net/bug.php?id=47990)關於這個函數沒有捕獲UTF-8中的代理,但我[不能再現](http:///codepad.viper-7.com/DFz1nJ)了。 – deceze 2012-01-18 08:51:45

4

我這個推薦功能(從symfony的工具包):

<?php 
    /** 
    * Checks if a string is an utf8. 
    * 
    * Yi Stone Li<[email protected]> 
    * Copyright (c) 2007 Yahoo! Inc. All rights reserved. 
    * Licensed under the BSD open source license 
    * 
    * @param string 
    * 
    * @return bool true if $string is valid UTF-8 and false otherwise. 
    */ 
    public static function isUTF8($string) 
    { 
    for ($idx = 0, $strlen = strlen($string); $idx < $strlen; $idx++) 
    { 
     $byte = ord($string[$idx]); 

     if ($byte & 0x80) 
     { 
     if (($byte & 0xE0) == 0xC0) 
     { 
      // 2 byte char 
      $bytes_remaining = 1; 
     } 
     else if (($byte & 0xF0) == 0xE0) 
     { 
      // 3 byte char 
      $bytes_remaining = 2; 
     } 
     else if (($byte & 0xF8) == 0xF0) 
     { 
      // 4 byte char 
      $bytes_remaining = 3; 
     } 
     else 
     { 
      return false; 
     } 

     if ($idx + $bytes_remaining >= $strlen) 
     { 
      return false; 
     } 

     while ($bytes_remaining--) 
     { 
      if ((ord($string[++$idx]) & 0xC0) != 0x80) 
      { 
      return false; 
      } 
     } 
     } 
    } 

    return true; 
    } 

但因爲它檢查字符串的所有字符,我不推薦使用它在一個大的文件。只需檢查前10行,即

<?php 
$handle = fopen("mycsv.csv", "r"); 
$check_string = ""; 
$line = 1; 
if ($handle) { 
    while ((($buffer = fgets($handle, 4096)) !== false) && $line < 11) { 
     $check_string .= $buffer; 
     $line++; 
    } 
    if (!feof($handle)) { 
     echo "Error: unexpected fgets() fail\n"; 
    } 
    fclose($handle); 

    var_dump(self::isUTF8($check_string)); 
}