以十六进制格式查看文件

查看文件的十六进制。

VS Code 插件 hexdump for VSCode

如果使用 VS Code,可以安装 hexdump for VSCode 这个插件,就可以很方便的查看文件的十六进制了。

其他软件

其他可以查看十六进制的软件包括 WinHex 等。

Linux 系统中自带 hexdump 命令可以查看十六进制。

一个小测试

之前看廖雪峰的 git 教程的时候,看到他说:

千万不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队使用了一个非常弱智的行为来保存UTF-8编码的文件,他们自作聪明地在每个文件开头添加了0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如,网页第一行可能会显示一个“?”,明明正确的程序一编译就报语法错误,等等,都是由记事本的弱智行为带来的。

想到他写这个教程已经过去很久了,于是打算自己测试一下。

测试之后发现 Windows 版本 1803(OS 内部版本 17134.648)这个版本的操作系统的记事本程序并不存在他说的那种情况。文件的开头就直接是字符的编码,并没有多余的字符。

意外的发现

查看的时候顺便测试了一下中文的编码。使用 Windows 记事本保存中文之后,编码是 GB2312

GB2312 编码格式下,一个汉字使用两个字节编码。

然后又测试了一下,发现 UTF-8 下,一个汉字使用三个字节编码。又想起来之前说 Java 中的一个 char 类型变量占两个字节的空间,可以表示汉字,就觉得有点奇怪,查了一下发现,Java 内部是采用 UTF-16 编码的,常见的汉字是占两个字节的。之所以说“常见的”汉字,是因为有一些汉字可能是要占四个字节的:

GBK编码,一个汉字占两个字节。

UTF-16编码,通常汉字占两个字节,CJKV扩展B区、扩展C区、扩展D区中的汉字占四个字节(一般字符的Unicode范围是U+0000至U+FFFF,而这些扩展部分的范围大于U+20000,因而要用两个UTF-16)。

UTF-8编码是变长编码,通常汉字占三个字节,扩展B区以后的汉字占四个字节。

来源:一个汉字占多少字节? - 知乎

另外,参考:Java 语言中一个字符占几个字节? - 知乎

另外还有一个讲的特别详细的博客:字符集与编码(四)——Unicode

这里有个网站可以方便地查询一个编码对应的字符:编码查询

进一步引申

Windows 的记事本在文本文件前添加的可能是 BOM。之前也遇到过一些情况,文本格式如果要保存为 UTF-8,存在 UTF8-with BOMUTF-8 without BOM

可以参考一下这个知乎回答:csv 文件打开乱码,有哪些方法可以解决?

评论中有人说:

BOM头不是微软定义的,而是ISO标准。反而是那些不遵守标准的应该谴责。

所以,我打算有时间去查一查相关的 ISO 标准和 BOM 的故事。