我在vim文档中看到了下面一段介绍字符集转换的内容:
Vim will automatically convert from one to another encoding in several places:
- When reading a file and 'fileencoding' is different from 'encoding'
- When writing a file and 'fileencoding' is different from 'encoding'
- When displaying characters and 'termencoding' is different from 'encoding'
- When reading input and 'termencoding' is different from 'encoding'
- When displaying messages and the encoding used for LC_MESSAGES differs from
'encoding' (requires a gettext version that supports this).
- When reading a Vim script where |:scriptencoding| is different from
'encoding'.
- When reading or writing a |viminfo| file.
我想知道谁在皈依谁?例如:
"When reading a file and 'fileencoding' is different from 'encoding'"
"fileencoding"是否已转换为"encoding(编码)"?还是将"encoding"转换为"fileencoding?"?
文件的实际字符集与文件编码和编码之间的关系是什么?
如果文件的实际字符集和fileencoding的值不相等,那么上述转换操作会破坏文件的内容吗?
更新:
例如:encoding的值为:utf-8,vim打开一个文件:foo,根据fileencodings匹配的fileencoding值:sjis(假设我不知道这个文件的实际编码。),我编辑了foo,并使用":wq"来保存和关闭vim窗口。如果我再次打开foo文件,这个文件的actualencoding是fileencoding指定的sji,还是上次编辑时编码指定的utf-8?
'encoding'
是Vim内任何缓冲区文本的内部表示;这就是Vim正在进行的工作。当您处理不同的字符集时(或者如果您不关心并在现代操作系统上工作),强烈建议将其设置为utf-8
,因为Unicode编码确保任何字符都可以表示,并且不会丢失信息。(UTF-8是Vim内部唯一支持的Unicode表示形式;也就是说,您不能让它使用像UTF-16这样的双字节编码。)
在Vim中打开文件时,会考虑'fileencodings'
中可能的编码列表(注意复数!):
这是开始编辑时考虑的字符编码列表现有文件。读取文件时,Vim尝试使用第一个提到的字符编码。如果检测到错误,则下一个错误列表中的已尝试。当发现有效的编码时,已设置"fileencoding"。
因此,如果一个文件看起来不对劲,这是可以调整的选项;或者,您可以通过++enc
参数显式覆盖检测,例如
:edit ++enc=sjis japanese.txt
现在,Vim具有文件的源编码(持久化为(单数!)'fileencoding'
;这是在原始编码中写回所需的),并将字符集(如果不同)转换为其内部'encoding'
。所有Vim命令都对此进行操作,在:write
上,转换以相反的方式进行(或可选地被:w ++enc=...
覆盖)。
结论
- 只要检测到/通过的编码是正确的,和假设内部
'encoding'
能够表示所有读取的字符(用utf-8
保证),就不会有数据丢失 - 同样,当原始编码存储在
'fileencoding'
中时,文件的写入会透明地转换回来。现在,可能是编辑引入了一个无法在文件编码中表示的字符(但由于Vim的内部Unicode编码,您可以在中对其进行编辑)。Vim将在写入时打印E513: write error, conversion failed
,您必须手动更改字符,或者选择不同的目标文件编码
示例
具有这些汉字字符日本
的文件在SJIS编码中表示如下:
93fa 967b 0a
每个汉字存储在两个字节中,然后在末尾有一个字节的换行符(LF)。
对于:set encoding=utf-8
,这在内部表示为(g8
可以告诉你这一点):
e697 a5e6 9cac 0a
在UTF-8中,每个汉字存储在三个字节中,第一个汉字是e6 97 a5
。
现在,如果我编辑文本,例如用(ASCII)括号和:write
括起来,我会得到:
2893 fa96 7b29 0a
恢复了原来的SJIS编码,每个汉字又是两个字节,现在添加了括号28
和29
如果我尝试在ä
字符中进行编辑,:write
就会因E513
错误而失败,因为该字符无法在SJIS中表示。