我正在開發一個涉及解析xls文件數據的php腳本。我正在使用庫phpexcelreader。所有主要工作,但我偶然發現一個奇怪的問題。某些文件被錯誤地解析。看起來xls文件可能在內部使用不同的字符編碼。至少,然後我通過iconv -f cp1251 -t utf8從我的腳本管道輸出,字符串得到糾正。如何應對PHP中不同編碼的xls文件?
Phpexcelreader有一個用於指定輸出編碼的選項,但看起來像缺少能力檢測輸入編碼。有任何想法嗎?
我正在開發一個涉及解析xls文件數據的php腳本。我正在使用庫phpexcelreader。所有主要工作,但我偶然發現一個奇怪的問題。某些文件被錯誤地解析。看起來xls文件可能在內部使用不同的字符編碼。至少,然後我通過iconv -f cp1251 -t utf8從我的腳本管道輸出,字符串得到糾正。如何應對PHP中不同編碼的xls文件?
Phpexcelreader有一個用於指定輸出編碼的選項,但看起來像缺少能力檢測輸入編碼。有任何想法嗎?
工作簿對象的_defaultEncoding屬性可以設置爲包含Excel文件使用的字符集,然後用於處理由讀者轉換爲UTF-16LE,但它不會努力識別內部字符集本身。
如果定義
define('SPREADSHEET_EXCEL_READER_TYPE_CODEPAGE', 0x0042);
其他SPREADSHEET_EXCEL_READER_TYPE定義中,然後修改switch語句在行464開始包括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)
重新創建_GetInt2d方法(這似乎已經從代碼在某一點剝離)作爲
function _GetInt2d($data, $pos)
{
return ord($data[$pos]) | (ord($data[$pos + 1]) << 8);
}
,並創建一個_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美分:
我剛剛更換了encodeUTF16與此一
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);
這些功能api_detect_encoding和api_convert_encoding可以在這個LIB中找到:
唉..謝謝你這樣詳細的解釋。你確定_defaultEncoding是表示內部編碼嗎?看起來工作表中的數據被轉碼爲UTF16-LE的_defaultEncoding(_encodeUTF16函數) – 2011-03-21 13:45:42
順便提一下,您提到了另外的讀者,您能否提出一個好的建議?我需要的只是讀取未格式化的單元格數據和維度。 – 2011-03-21 13:50:46
PHPExcel是我在PHP中使用電子表格數據時推薦的庫;但我確實有偏見,因爲我是開發人員之一 – 2011-03-21 14:04:28