很多刚接触编程、网络协议的朋友都会被「文字、编码、字节、十六进制」这几个概念绕晕为什么存个中文打开文件就变成了乱码抓包抓到一堆十六进制字符串不知道是什么文字游戏配置里的名字是十六进制想改成自己的名字不知道怎么转这篇文章用最通俗的比喻从零讲透所有核心逻辑附带完整的 Python 代码复制就能用哪怕你是刚学编程的小白也能 10 分钟搞定所有转换一、核心逻辑文字在电脑里到底是怎么存的很多人搞不懂这些概念其实核心逻辑特别简单 电脑只认识 0 和 1根本不认识 “中文、英文、符号” 这些文字。所以我们要把文字 “翻译” 成电脑能懂的东西这个翻译的过程就叫编码。反过来当我们要把电脑里的东西读出来的时候就要把电脑的语言 “翻译” 回我们能懂的文字这个过程就叫解码。整个流程是这样的1、我们的文字 → 编码 → 电脑的字节 → 十六进制我们能看懂的格式 2、十六进制 → 字节 → 解码 → 我们的文字举个例子 我们的文字是 “频”用 UTF-16 大端编码之后变成了电脑的两个字节然后我们把这两个字节用十六进制展示出来就是98,91。二、搞懂进制二进制、十进制、十六进制到底啥区别很多人一听到 “进制” 就头大其实这三个就是不同的 “计数方式” 而已就像我们平时用斤西方用磅只是单位不一样东西是同一个。二进制电脑的原生语言电脑的底层是电路只有通电和断电两种状态对应就是 0 和 1所以电脑天生就用二进制只有 0 和 1 两个数字。 比如数字 10用二进制写就是1010。但是二进制太长了一个字节就有 8 位二进制比如 255 的二进制是11111111写起来太麻烦我们读着也累。十进制我们日常用的就是我们平时数数用的0-9 十个数字这个大家都懂不用多说。十六进制程序员的 “简写工具”为了方便我们读字节程序员就发明了十六进制用 0-9 加 A-F对应 10-15来计数刚好两个十六进制字符就能表示一个字节 比如刚才的 255用二进制要写 8 个 1用十六进制只要写FF是不是短了很多比如这串十六进制53 CC 5E 08其实就是 4 个字节每个空格或者逗号分开的两个字符就是一个字节是不是一目了然三、Python 里的进制转换一行代码搞定Python 已经把所有转换都帮你写好了不用自己算直接调用就行复制下面的代码就能跑十进制转其他进制比如我们有个数字 255想转成二进制、八进制、十六进制num 255 print(bin(num)) # 转二进制输出0b11111111 print(oct(num)) # 转八进制输出0o377 print(hex(num)) # 转十六进制输出0xff前面的0b、0o、0x只是告诉你这是什么进制不用管它。其他进制转十进制反过来如果你有一个二进制 / 八进制 / 十六进制的字符串想转成我们日常用的十进制print(int(11111111, 2)) # 二进制转十进制输出255 print(int(377, 8)) # 八进制转十进制输出255 print(int(ff, 16)) # 十六进制转十进制输出255这里的第二个参数就是告诉 Python“我给你的这个字符串是 XX 进制的你帮我转成十进制”。把十六进制补成固定长度有时候我们需要把短的十六进制前面补 0比如数字 15我们想写成两位的0f而不是f可以用这个格式num 15 print(f{num:02x}) # 不足2位补0输出0f print(f{num:04x}) # 不足4位补0输出000f02x的意思就是用小写的十六进制不足 2 位的话前面补 0非常好用。四、文字转十六进制把中文变成协议里的字符串现在我们来做最常用的操作把我们的文字转成十六进制字符串比如要改游戏配置、或者要拼协议数据的时候就会用到。这里要注意不同的编码方式转出来的结果是不一样的别搞混了常用的有三种1、UTF-8网页 / 文件的通用编码这是现在最常用的编码我们的网页、TXT 文件、接口数据基本都是用 UTF-8大部分场景下用它就没错。text 中文 # 把文字编码成字节再转成逗号分隔的十六进制 hex_text ,.join(f{b:02x} for b in text.encode(utf-8)) print(hex_text) # 输出e4,b8,ad,e6,96,872、UTF-16 大端BEWindows / 协议常用编码很多 Windows 系统的程序、二进制协议、老游戏的配置文件都喜欢用 UTF-16 大端编码这种编码里一个常用中文字符刚好占 2 个字节非常整齐。text 频 hex_text ,.join(f{b:02x} for b in text.encode(utf-16-be)) print(hex_text) # 输出98,913、UTF-16 小端LE只是字节顺序反了还有一种是 UTF-16 小端它和大端的内容是一样的只是字节的顺序反过来了而已就像你写数字大端是从左到右写小端是从右到左写。 比如 “频” 的大端是98,91小端就是91,98就这么简单text 频 hex_text ,.join(f{b:02x} for b in text.encode(utf-16-le)) print(hex_text) # 输出91,98小提示怎么知道我该用大端还是小端 一般来说如果是 Windows 的老程序、游戏配置、网络协议大部分是大端BE如果是一些嵌入式设备可能会用小端不确定的话可以试一下转出来是正常的中文就对了。五、十六进制转文字把一堆字符串还原成中文反过来如果你拿到了一堆十六进制字符串想还原成中文也很简单还是用对应的编码解码就行比如我们拿到了一段 UTF-16 大端的十六进制53,cc,5e,08,7c,fb,7e,df,00,00,00,00hex_str 53,cc,5e,08,7c,fb,7e,df,00,00,00,00 # 第一步把十六进制字符串转成字节数据 data bytes(int(x, 16) for x in hex_str.split(,)) # 第二步去掉末尾没用的空字节很多协议会补0对齐然后解码成文字 text data.rstrip(b\x00).decode(utf-16-be) print(text) # 输出修改模式这里解释一下两个细节split(,)把逗号分开的十六进制拆成一个个的字节rstrip(b\x00)很多协议或者配置文件为了让每个字符串长度一样会在短字符串后面补一堆空的00字节这些是没用的我们把它去掉不然转出来的文字后面会有看不见的空字符。六、批量转换一次处理一堆数据不用一个个来如果你有一堆十六进制数据比如 100 个配置项一个个转太慢了我们可以用字典批量处理一次搞定# 把你的数据填到这里key是名字value是十六进制字符串 items { name1: 53,cc,5e,08,7c,fb,7e,df,00,00,00,00, name2: 53,cc,5e,08,67,2c,57,30,00,00,00,00, name3: 6a,21,5f,0f,4e,09,00,00,00,00, } # 批量转换 for key, hex_str in items.items(): data bytes(int(x, 16) for x in hex_str.split(,)) text data.rstrip(b\x00).decode(utf-16-be) print(key, text)运行之后就会输出name1 修改模式 name2 测试玩家 name3 自定义名这个特别适合处理配置文件、游戏存档、设备协议的批量数据省超多时间。七、Unicode每个汉字的唯一身份证讲完了编码我们再讲一个很重要的概念Unicode。以前没有 Unicode 的时候每个国家都自己搞编码中国有 GBK日本有 Shift-JIS同一个字节在中文系统里是 “中”在日文系统里就变成了别的字这就是乱码的根源后来大家就搞了个统一的标准Unicode给全世界所有的字符都分配了一个唯一的编号这个编号就叫码点就像每个字符的身份证号全世界通用不管你用什么编码这个身份证号是不变的。比如中 → 身份证号U4E2D文 → 身份证号U6587频 → 身份证号U9891有了这个就再也不会出现 “同一个字在不同系统不一样” 的问题了。Python 里怎么查 Unicode 身份证号还是一行代码# 查文字的Unicode text 频 for ch in text: print(ch, hex(ord(ch))) # 输出频 0x9891反过来用身份证号找文字# 用Unicode查文字 print(chr(0x9891)) # 输出频是不是很简单ord就是查身份证chr就是用身份证找人记下来这两个函数八、常用汉字的 Unicode 范围知道就行不用记Unicode 里的汉字分了好几个区大部分我们日常用的汉字都在U4E00 - U9FFF这个基本区里剩下的都是生僻字、古文字之类的日常用不到U3400 - U4DBF CJK 扩展 A生僻字 U4E00 - U9FFF 基本汉字区我们日常用的所有汉字都在这 U20000 - U2A6DF CJK 扩展 B超生僻字比如古籍里的字 U2A700 - U2B73F CJK 扩展 C U2B740 - U2B81F CJK 扩展 D U2B820 - U2CEAF CJK 扩展 E U2CEB0 - U2EBEF CJK 扩展 F U30000 - U3134F CJK 扩展 G小白只要记住日常处理中文基本都在U4E00 - U9FFF里其他的不用管。九、怎么快速查 Unicode在线工具 Python 都可以有时候你不想写代码就想查单个字的 Unicode用在线工具就很方便在线查询网站这几个网站都很好用直接输入汉字或者 U 编号就能查Unicode 官方图表Compart Unicode 查询Symbl.cc Unicode 工具汉字字符集编码查询中文字符集编码GB2312、BIG5、GBK、GB18030、UnicodePython 批量查询如果你要查一堆字还是用 Python 方便# 文字查Unicode ch 频 print(hex(ord(ch))) # 输出0x9891 # Unicode查文字 code 0x9891 print(chr(code)) # 输出频 # 查看一段连续的汉字比如从U4E00开始的16个汉字 for code in range(0x4E00, 0x4E10): print(hex(code), chr(code))十、通用转换脚本复制粘贴就能用不用自己写我把所有常用的功能都打包成了三个函数你直接复制到你的 Python 里想用就调用不用管里面的细节# 1. 文字转十六进制默认用UTF-16-BE需要的话可以改encoding def text_to_hex(text, encodingutf-16-be): return ,.join(f{b:02x} for b in text.encode(encoding)) # 2. 十六进制转文字默认用UTF-16-BE def hex_to_text(hex_str, encodingutf-16-be): data bytes(int(x.strip(), 16) for x in hex_str.split(,) if x.strip()) return data.rstrip(b\x00).decode(encoding) # 3. 查看文字的Unicode码点 def show_unicode(text): for ch in text: print(ch, fU{ord(ch):04X}, hex(ord(ch))) # ------------------- 下面是测试你可以改成自己的数据 ------------------- print(text_to_hex(频)) # 输出98,91 print(text_to_hex(修改模式)) # 输出53,cc,5e,08,7c,fb,7e,df print(hex_to_text(53,cc,5e,08,7c,fb,7e,df,00,00,00,00)) # 输出修改模式 show_unicode(中文频) # 输出 # 中 U4E2D 0x4e2d # 文 U6587 0x6587 # 频 U9891 0x9891就这么简单复制完把测试数据改成你自己的直接运行就出结果了十一、核心知识点总结记这 8 句话就够了文字不能直接存要先编码成电脑能懂的字节字节太长了我们用十六进制来展示好读不同的编码方式转出来的十六进制不一样别搞混了网页、普通文件基本用 UTF-8Windows 系统、二进制协议、游戏配置很多用 UTF-16大端小端只是字节的顺序反了内容没变Python 里encode是文字转字节decode是字节转文字ord是查汉字的 Unicode 身份证chr是用身份证找汉字常见问题为什么会乱码很多人遇到乱码其实原因特别简单你编码用的方式和解码用的方式不一样就像你把中文翻译成英文结果用日语的字典去翻译肯定看不懂啊 比如你用 UTF-16 编码的文字结果用 UTF-8 去解码那肯定就乱码了只要把编码方式改成一样的就好了。好了看完这篇你已经搞定了所有文字、编码、字节、十六进制的转换了不管是处理协议、改配置、还是解决乱码都没问题了赶紧把脚本复制去试试吧
文字编码与进制转换指南
很多刚接触编程、网络协议的朋友都会被「文字、编码、字节、十六进制」这几个概念绕晕为什么存个中文打开文件就变成了乱码抓包抓到一堆十六进制字符串不知道是什么文字游戏配置里的名字是十六进制想改成自己的名字不知道怎么转这篇文章用最通俗的比喻从零讲透所有核心逻辑附带完整的 Python 代码复制就能用哪怕你是刚学编程的小白也能 10 分钟搞定所有转换一、核心逻辑文字在电脑里到底是怎么存的很多人搞不懂这些概念其实核心逻辑特别简单 电脑只认识 0 和 1根本不认识 “中文、英文、符号” 这些文字。所以我们要把文字 “翻译” 成电脑能懂的东西这个翻译的过程就叫编码。反过来当我们要把电脑里的东西读出来的时候就要把电脑的语言 “翻译” 回我们能懂的文字这个过程就叫解码。整个流程是这样的1、我们的文字 → 编码 → 电脑的字节 → 十六进制我们能看懂的格式 2、十六进制 → 字节 → 解码 → 我们的文字举个例子 我们的文字是 “频”用 UTF-16 大端编码之后变成了电脑的两个字节然后我们把这两个字节用十六进制展示出来就是98,91。二、搞懂进制二进制、十进制、十六进制到底啥区别很多人一听到 “进制” 就头大其实这三个就是不同的 “计数方式” 而已就像我们平时用斤西方用磅只是单位不一样东西是同一个。二进制电脑的原生语言电脑的底层是电路只有通电和断电两种状态对应就是 0 和 1所以电脑天生就用二进制只有 0 和 1 两个数字。 比如数字 10用二进制写就是1010。但是二进制太长了一个字节就有 8 位二进制比如 255 的二进制是11111111写起来太麻烦我们读着也累。十进制我们日常用的就是我们平时数数用的0-9 十个数字这个大家都懂不用多说。十六进制程序员的 “简写工具”为了方便我们读字节程序员就发明了十六进制用 0-9 加 A-F对应 10-15来计数刚好两个十六进制字符就能表示一个字节 比如刚才的 255用二进制要写 8 个 1用十六进制只要写FF是不是短了很多比如这串十六进制53 CC 5E 08其实就是 4 个字节每个空格或者逗号分开的两个字符就是一个字节是不是一目了然三、Python 里的进制转换一行代码搞定Python 已经把所有转换都帮你写好了不用自己算直接调用就行复制下面的代码就能跑十进制转其他进制比如我们有个数字 255想转成二进制、八进制、十六进制num 255 print(bin(num)) # 转二进制输出0b11111111 print(oct(num)) # 转八进制输出0o377 print(hex(num)) # 转十六进制输出0xff前面的0b、0o、0x只是告诉你这是什么进制不用管它。其他进制转十进制反过来如果你有一个二进制 / 八进制 / 十六进制的字符串想转成我们日常用的十进制print(int(11111111, 2)) # 二进制转十进制输出255 print(int(377, 8)) # 八进制转十进制输出255 print(int(ff, 16)) # 十六进制转十进制输出255这里的第二个参数就是告诉 Python“我给你的这个字符串是 XX 进制的你帮我转成十进制”。把十六进制补成固定长度有时候我们需要把短的十六进制前面补 0比如数字 15我们想写成两位的0f而不是f可以用这个格式num 15 print(f{num:02x}) # 不足2位补0输出0f print(f{num:04x}) # 不足4位补0输出000f02x的意思就是用小写的十六进制不足 2 位的话前面补 0非常好用。四、文字转十六进制把中文变成协议里的字符串现在我们来做最常用的操作把我们的文字转成十六进制字符串比如要改游戏配置、或者要拼协议数据的时候就会用到。这里要注意不同的编码方式转出来的结果是不一样的别搞混了常用的有三种1、UTF-8网页 / 文件的通用编码这是现在最常用的编码我们的网页、TXT 文件、接口数据基本都是用 UTF-8大部分场景下用它就没错。text 中文 # 把文字编码成字节再转成逗号分隔的十六进制 hex_text ,.join(f{b:02x} for b in text.encode(utf-8)) print(hex_text) # 输出e4,b8,ad,e6,96,872、UTF-16 大端BEWindows / 协议常用编码很多 Windows 系统的程序、二进制协议、老游戏的配置文件都喜欢用 UTF-16 大端编码这种编码里一个常用中文字符刚好占 2 个字节非常整齐。text 频 hex_text ,.join(f{b:02x} for b in text.encode(utf-16-be)) print(hex_text) # 输出98,913、UTF-16 小端LE只是字节顺序反了还有一种是 UTF-16 小端它和大端的内容是一样的只是字节的顺序反过来了而已就像你写数字大端是从左到右写小端是从右到左写。 比如 “频” 的大端是98,91小端就是91,98就这么简单text 频 hex_text ,.join(f{b:02x} for b in text.encode(utf-16-le)) print(hex_text) # 输出91,98小提示怎么知道我该用大端还是小端 一般来说如果是 Windows 的老程序、游戏配置、网络协议大部分是大端BE如果是一些嵌入式设备可能会用小端不确定的话可以试一下转出来是正常的中文就对了。五、十六进制转文字把一堆字符串还原成中文反过来如果你拿到了一堆十六进制字符串想还原成中文也很简单还是用对应的编码解码就行比如我们拿到了一段 UTF-16 大端的十六进制53,cc,5e,08,7c,fb,7e,df,00,00,00,00hex_str 53,cc,5e,08,7c,fb,7e,df,00,00,00,00 # 第一步把十六进制字符串转成字节数据 data bytes(int(x, 16) for x in hex_str.split(,)) # 第二步去掉末尾没用的空字节很多协议会补0对齐然后解码成文字 text data.rstrip(b\x00).decode(utf-16-be) print(text) # 输出修改模式这里解释一下两个细节split(,)把逗号分开的十六进制拆成一个个的字节rstrip(b\x00)很多协议或者配置文件为了让每个字符串长度一样会在短字符串后面补一堆空的00字节这些是没用的我们把它去掉不然转出来的文字后面会有看不见的空字符。六、批量转换一次处理一堆数据不用一个个来如果你有一堆十六进制数据比如 100 个配置项一个个转太慢了我们可以用字典批量处理一次搞定# 把你的数据填到这里key是名字value是十六进制字符串 items { name1: 53,cc,5e,08,7c,fb,7e,df,00,00,00,00, name2: 53,cc,5e,08,67,2c,57,30,00,00,00,00, name3: 6a,21,5f,0f,4e,09,00,00,00,00, } # 批量转换 for key, hex_str in items.items(): data bytes(int(x, 16) for x in hex_str.split(,)) text data.rstrip(b\x00).decode(utf-16-be) print(key, text)运行之后就会输出name1 修改模式 name2 测试玩家 name3 自定义名这个特别适合处理配置文件、游戏存档、设备协议的批量数据省超多时间。七、Unicode每个汉字的唯一身份证讲完了编码我们再讲一个很重要的概念Unicode。以前没有 Unicode 的时候每个国家都自己搞编码中国有 GBK日本有 Shift-JIS同一个字节在中文系统里是 “中”在日文系统里就变成了别的字这就是乱码的根源后来大家就搞了个统一的标准Unicode给全世界所有的字符都分配了一个唯一的编号这个编号就叫码点就像每个字符的身份证号全世界通用不管你用什么编码这个身份证号是不变的。比如中 → 身份证号U4E2D文 → 身份证号U6587频 → 身份证号U9891有了这个就再也不会出现 “同一个字在不同系统不一样” 的问题了。Python 里怎么查 Unicode 身份证号还是一行代码# 查文字的Unicode text 频 for ch in text: print(ch, hex(ord(ch))) # 输出频 0x9891反过来用身份证号找文字# 用Unicode查文字 print(chr(0x9891)) # 输出频是不是很简单ord就是查身份证chr就是用身份证找人记下来这两个函数八、常用汉字的 Unicode 范围知道就行不用记Unicode 里的汉字分了好几个区大部分我们日常用的汉字都在U4E00 - U9FFF这个基本区里剩下的都是生僻字、古文字之类的日常用不到U3400 - U4DBF CJK 扩展 A生僻字 U4E00 - U9FFF 基本汉字区我们日常用的所有汉字都在这 U20000 - U2A6DF CJK 扩展 B超生僻字比如古籍里的字 U2A700 - U2B73F CJK 扩展 C U2B740 - U2B81F CJK 扩展 D U2B820 - U2CEAF CJK 扩展 E U2CEB0 - U2EBEF CJK 扩展 F U30000 - U3134F CJK 扩展 G小白只要记住日常处理中文基本都在U4E00 - U9FFF里其他的不用管。九、怎么快速查 Unicode在线工具 Python 都可以有时候你不想写代码就想查单个字的 Unicode用在线工具就很方便在线查询网站这几个网站都很好用直接输入汉字或者 U 编号就能查Unicode 官方图表Compart Unicode 查询Symbl.cc Unicode 工具汉字字符集编码查询中文字符集编码GB2312、BIG5、GBK、GB18030、UnicodePython 批量查询如果你要查一堆字还是用 Python 方便# 文字查Unicode ch 频 print(hex(ord(ch))) # 输出0x9891 # Unicode查文字 code 0x9891 print(chr(code)) # 输出频 # 查看一段连续的汉字比如从U4E00开始的16个汉字 for code in range(0x4E00, 0x4E10): print(hex(code), chr(code))十、通用转换脚本复制粘贴就能用不用自己写我把所有常用的功能都打包成了三个函数你直接复制到你的 Python 里想用就调用不用管里面的细节# 1. 文字转十六进制默认用UTF-16-BE需要的话可以改encoding def text_to_hex(text, encodingutf-16-be): return ,.join(f{b:02x} for b in text.encode(encoding)) # 2. 十六进制转文字默认用UTF-16-BE def hex_to_text(hex_str, encodingutf-16-be): data bytes(int(x.strip(), 16) for x in hex_str.split(,) if x.strip()) return data.rstrip(b\x00).decode(encoding) # 3. 查看文字的Unicode码点 def show_unicode(text): for ch in text: print(ch, fU{ord(ch):04X}, hex(ord(ch))) # ------------------- 下面是测试你可以改成自己的数据 ------------------- print(text_to_hex(频)) # 输出98,91 print(text_to_hex(修改模式)) # 输出53,cc,5e,08,7c,fb,7e,df print(hex_to_text(53,cc,5e,08,7c,fb,7e,df,00,00,00,00)) # 输出修改模式 show_unicode(中文频) # 输出 # 中 U4E2D 0x4e2d # 文 U6587 0x6587 # 频 U9891 0x9891就这么简单复制完把测试数据改成你自己的直接运行就出结果了十一、核心知识点总结记这 8 句话就够了文字不能直接存要先编码成电脑能懂的字节字节太长了我们用十六进制来展示好读不同的编码方式转出来的十六进制不一样别搞混了网页、普通文件基本用 UTF-8Windows 系统、二进制协议、游戏配置很多用 UTF-16大端小端只是字节的顺序反了内容没变Python 里encode是文字转字节decode是字节转文字ord是查汉字的 Unicode 身份证chr是用身份证找汉字常见问题为什么会乱码很多人遇到乱码其实原因特别简单你编码用的方式和解码用的方式不一样就像你把中文翻译成英文结果用日语的字典去翻译肯定看不懂啊 比如你用 UTF-16 编码的文字结果用 UTF-8 去解码那肯定就乱码了只要把编码方式改成一样的就好了。好了看完这篇你已经搞定了所有文字、编码、字节、十六进制的转换了不管是处理协议、改配置、还是解决乱码都没问题了赶紧把脚本复制去试试吧