如何应对PHP中不同编码的xls文件?

我正在开发一个涉及parsingxls文件数据的php脚本。 我正在使用库phpexcelreader 。 所有的主要工作,但我偶然发现一个奇怪的问题。 有些文件被错误地parsing。 看起来像xls文件可能会在内部使用不同的字符编码。 至less,然后我通过iconv -f cp1251 -t utf8从我的脚本pipe道输出,string得到纠正。

Phpexcelreader有一个用于指定输出编码的选项,但看起来像缺less能力检测input编码。 有任何想法吗?

工作簿对象的_defaultEncoding属性可以被设置为包含Excel文件所使用的字符集,然后用于处理由读者转换为UTF-16LE,但是它没有努力识别内部字符集本身。

如果你定义

define('SPREADSHEET_EXCEL_READER_TYPE_CODEPAGE', 0x0042); 

在其他SPREADSHEET_EXCEL_READER_TYPE定义中,然后修改从第464行开始的switch语句,以包含SPREADSHEET_EXCEL_READER_TYPE_CODEPAGE的情况。 这种情况下的逻辑需要是这样的:

 $length = $this->_GetInt2d($this->_data, $pos + 2); $recordData = substr($this->_data, $pos + 4, $length); // move stream pointer to next record $pos += 4 + $length; // offset: 0; size: 2; code page identifier $codepage = $this->_GetInt2d($recordData, 0); $codepage = $this->_CodePageNumberToName($codepage) 

重新创build_GetInt2d方法(似乎已经从代码中删除)作为

 function _GetInt2d($data, $pos) { return ord($data[$pos]) | (ord($data[$pos + 1]) << 8); } 

并创build一个_CodePageNumberToName方法来返回其数值的代码页名称:

 function _CodePageNumberToName($codePage = '1252') { switch ($codePage) { case 367: return 'ASCII'; break; // ASCII case 437: return 'CP437'; break; // OEM US case 720: throw new Exception('Code page 720 not supported.'); break; // OEM Arabic case 737: return 'CP737'; break; // OEM Greek case 775: return 'CP775'; break; // OEM Baltic case 850: return 'CP850'; break; // OEM Latin I case 852: return 'CP852'; break; // OEM Latin II (Central European) case 855: return 'CP855'; break; // OEM Cyrillic case 857: return 'CP857'; break; // OEM Turkish case 858: return 'CP858'; break; // OEM Multilingual Latin I with Euro case 860: return 'CP860'; break; // OEM Portugese case 861: return 'CP861'; break; // OEM Icelandic case 862: return 'CP862'; break; // OEM Hebrew case 863: return 'CP863'; break; // OEM Canadian (French) case 864: return 'CP864'; break; // OEM Arabic case 865: return 'CP865'; break; // OEM Nordic case 866: return 'CP866'; break; // OEM Cyrillic (Russian) case 869: return 'CP869'; break; // OEM Greek (Modern) case 874: return 'CP874'; break; // ANSI Thai case 932: return 'CP932'; break; // ANSI Japanese Shift-JIS case 936: return 'CP936'; break; // ANSI Chinese Simplified GBK case 949: return 'CP949'; break; // ANSI Korean (Wansung) case 950: return 'CP950'; break; // ANSI Chinese Traditional BIG5 case 1200: return 'UTF-16LE'; break; // UTF-16 (BIFF8) case 1250: return 'CP1250'; break; // ANSI Latin II (Central European) case 1251: return 'CP1251'; break; // ANSI Cyrillic case 0: // CodePage is not always correctly set when the xls file was saved by Apple's Numbers program case 1252: return 'CP1252'; break; // ANSI Latin I (BIFF4-BIFF7) case 1253: return 'CP1253'; break; // ANSI Greek case 1254: return 'CP1254'; break; // ANSI Turkish case 1255: return 'CP1255'; break; // ANSI Hebrew case 1256: return 'CP1256'; break; // ANSI Arabic case 1257: return 'CP1257'; break; // ANSI Baltic case 1258: return 'CP1258'; break; // ANSI Vietnamese case 1361: return 'CP1361'; break; // ANSI Korean (Johab) case 10000: return 'MAC'; break; // Apple Roman case 32768: return 'MAC'; break; // Apple Roman case 32769: throw new Exception('Code page 32769 not supported.'); break; // ANSI Latin I (BIFF2-BIFF3) case 65001: return 'UTF-8'; break; // Unicode (UTF-8) } } 

并将返回的值存储在$ _defaultEncoding中

另外,切换到一个Excel阅读器,可以正确处理代码页的第一位

我的2美分:

我刚刚用这个replace了编码UTF16

  function _encodeUTF16($string, $check = false) { if ($check) { $from = api_detect_encoding($string); $string = api_convert_encoding($string, $this->_defaultEncoding, $from); return $string; } $string = api_convert_encoding($string, $this->_defaultEncoding, 'UTF-16LE'); return $string; 

并更改568行

 $retstr = ($asciiEncoding) ? $this->_encodeUTF16($retstr, true) : $this->_encodeUTF16($retstr); 

可以在这个lib中find这些函数api_detect_encoding和api_convert_encoding:

http://code.google.com/p/chamilo/source/browse/main/inc/lib/internationalization.lib.php?repo=classic