为何Vim中set fileencoding=cp936在纯英文文件下不生效?
核心原因:Vim的编码检测优先级与ASCII兼容特性
Vim打开已有文件时,不会直接沿用set fenc指定的默认编码,而是按照fencs配置的顺序自动检测文件内容的编码格式,匹配到第一个兼容的编码后,就会将其设为fileencoding。
纯英文文件(test1.c)的情况
纯英文内容属于ASCII字符集,而ASCII是UTF-8的子集,同时也兼容CP936(GBK)编码。由于你的fencs配置中utf-8排在gbk(CP936是GBK的扩展)之前:
set fencs=ucs-bom,utf-8,gbk,gb18030,utf-16,big5
Vim检测到文件内容完全符合UTF-8的编码规则,因此优先将fileencoding设为utf-8。而file命令显示为"ASCII文本",是因为纯ASCII内容的文件,file工具会优先识别为ASCII——这和Vim的编码检测逻辑不冲突,因为ASCII本身就是UTF-8的基础子集。
含中文文件(test2.c)的情况
中文内容在CP936中的编码是特定的双字节序列,这些序列不符合UTF-8的编码规范(UTF-8对中文的编码有严格的多字节位模式要求)。因此Vim会跳过utf-8,继续按fencs顺序检测,直到匹配到gbk/cp936,最终将fileencoding设为cp936。
至于file命令显示为"ISO-8859文本",是因为CP936的中文字节在单字节的ISO-8859-1编码中会被识别为普通扩展ASCII字符,file工具没有准确识别出这是CP936编码的文件,属于工具自身的检测局限性。
补充说明
set fenc=cp936仅作用于新建空白文件时的默认编码(也就是你第一次创建文件时fileencoding=cp936的原因),但当文件被保存并重新打开时,Vim会基于文件实际内容和fencs的优先级重新检测编码,而非沿用fenc的设置。
内容的提问来源于stack exchange,提问作者Da Wang

