一、問題的出現: 有一天有人發了個.zip的文件給我。我unzip它,卻發現中文名的文件解出來文件名是錯的。 二、上網尋找問題答案: 有網友告訴我,是因為winzip用某種OEM方式修改文件名所致(後來證明這個說法是錯的), 要用另外一個某某更強大的zip並關閉OEM
一、問題的出現: 有一天有人發了個.zip的文件給我。我unzip它,卻發現中文名的文件解出來文件名是錯的。
二、上網尋找問題答案: 有網友告訴我,是因為winzip用某種OEM方式修改文件名所致(後來證明這個說法是錯的), 要用另外一個某某更強大的zip並關閉OEM方式再壓縮才行。 但我想我們不應讓別人必須用某某個軟件來將就Unzip。
三、臨時解決問題:*本文所提供的方法是臨時性的解決辦法* 1. 到底發生了什麼問題?
---------------------------
實驗1:在
Linux下用zip壓縮兩個中文名文件並命名為1.zip,
結果1:在
windows98下用Winzip打開中文件名沒問題。
實驗2: 在windows98下用Winzip壓縮相同的兩個中文名文件並命名為2.zip,
結果2:在Linux下用Unzip打開中文名出來的完全不對,但長度一致。
實驗3: 用二進制查看器比較兩個壓縮文件(1.zip,2.zip),
結果3:發現兩個壓縮文件中的文件名二進制編碼是完全一樣的。
實驗4: Unzip比較兩個壓縮文件的信息
結果4: 除文件名不同以外,就是類型(type)不同,一個是
Unix,一個是fat。
結論:
winzip存文件名的方法與Unzip完全相同,
問題在Unzip中,它將類型為fat的壓縮文件中的文件名作了另外的解釋。
2.解決問題的方法
***************************************
*修改Unzip讓它對文件名不作另外的解釋。*
***************************************
找呀找......,終於找到了(我是通過學習了emacs及etags來找的)
==============================================================================
在 Unzip-5.42 源文件包中的文件 unzpriv.h 約第 2396行上下
==============================================================================
/* Convert filename (and file comment string) into "internal" charset.
* This macro assumes that Zip entry filenames are coded in OEM (IBM DOS)
* codepage when made on
* -> DOS (this includes 16-bit
Windows 3.1) (FS_FAT_)
* -> OS/2 (FS_HPFS_)
* -> Win95/WinNT with Nico Mak's WinZip (FS_NTFS_ && hostver == "5.0")
* EXCEPTIONS:
* PKZIP for Windows 2.5 and 2.6 flag their entries as "FS_FAT_", but the
* filename stored in the local header is coded in Windows ANSI (ISO 8859-1).
* Likewise, PKZIP for UNIX 2.51 flags its entries as "FS_FAT_", but the
* filenames stored in BOTH the local and the central header are coded
* in the local system's codepage (usually ANSI codings like ISO 8859-1).
*
* All other ports are assumed to code zip entry filenames in ISO 8859-1.
*/
#ifndef Ext_ASCII_TO_Native
# define Ext_ASCII_TO_Native(string, hostnum, hostver, isuxatt, islochdr) \
if (((hostnum) == FS_FAT_ && \
!(((islochdr) || (isuxatt)) && \
(hostver) >= 25 && (hostver) <= 26)) || \
(hostnum) == FS_HPFS_ || \
((hostnum) == FS_NTFS_ && (hostver) == 50)) { \
_OEM_INTERN((string)); \
} else { \
_ISO_INTERN((string)); \
}
#endif
=============================================================================
*******************************************
*臨時修正的方法:全部都用函數_ISO_INTERN()*
*******************************************
修改如下:
=============================================================================
#ifndef Ext_ASCII_TO_Native
# define Ext_ASCII_TO_Native(string, hostnum, hostver, isuxatt, islochdr) \
/* if (((hostnum) == FS_FAT_ && \
* !(((islochdr) || (isuxatt)) && \
* (hostver) >= 25 && (hostver) <= 26)) || \
* (hostnum) == FS_HPFS_ || \
* ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \
* _OEM_INTERN((string)); \
* } else { \ */
_ISO_INTERN((string)); \
/* } */
#endif
==============================================================================
編譯成功,試一試,正確認出winzip壓縮的中文名!!!
==============================================================================
四、方法的局限性和臨時性: ***************************************************************
*方法的缺點很明顯,不能正確支持那幾種作了特殊處理的文件名了!!!*
*所以請高手指教更優的方法!!! *
***************************************************************