VIM如何执行字符集转换



我在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编码,每个汉字又是两个字节,现在添加了括号2829

如果我尝试在ä字符中进行编辑,:write就会因E513错误而失败,因为该字符无法在SJIS中表示。

最新更新