好好爱自己!

hex编码,用途是什么,为什么需要hex编码呢?

hex编码, 意义是什么呢?

 

https://stackoverflow.com/questions/39235626/string-does-what-i-hoped-strconv-itoa-would-do

strconv.Itoa formats an integer as a decimal string. Example: strconv.Itoa(65) and strconv.Itoa('A') return the string "65".

string(intValue) yields a string containing the UTF-8 representation of the integer. Example: string('A') and string(65) evaluate to the string "A".

Experience has shown that many people erroneously expect string(intValue) to return the decimal representation of the integer value. Because this expectation is so common, the Go 1.15 version of go vet warns about string(intValue) conversions when the type of the integer value is not rune or byte (read details here).

 

fmt.Println(string([]byte{231,149,140}))

上面这行,输出的是: 界  这个字符串!!!  string(intvalue) yields a string containing the utf-8 representation of the integer.

 

fmt.Println([]byte(string(-1)))          // 输出: [239 191 189]

https://golang.org/ref/spec#Conversions_to_and_from_a_string_type

 

 

 

 

package main

import (
    "encoding/hex"
    "fmt"
)

func main() {
    msg := []byte("Hello 世界")

    encoded := hex.EncodeToString(msg)
    fmt.Println(encoded)
    // 48656c6c6f20e4b896e7958c

    //encoded = "4769676162697445746865726E6574302F302F323400"
    decoded, _ := hex.DecodeString(encoded)
    fmt.Println(decoded)
    // Hello 世界

    fmt.Println(hex.EncodeToString([]byte{231,149,140}))
    fmt.Println(hex.EncodeToString([]byte("界")))
}

  

 

----------------------------------------------------------

参考:https://www.dazhuanlan.com/2020/02/18/5e4b4695cf02d/?__cf_chl_jschl_tk__=a44cdade9db80549c3703c98848bdbece682e831-1609731063-0-AfCErvV5QtvVwrawxJwEnJ6xrX-j0O6GvMm_GY3hg9peN7FhZrGnWCNeinH3oriOBwadP-D1N6Igvnw1ZQ1cqrn1vFlSt2DuYHj0GeX2KcciBuzpnQxMsVwrRR-_TAEITc5N6t4zgI7mfL7VEMqIU2bWmqs4YpUhGMb5sl8k8la9WN4oRzI4q-peoRwuQGNzMDXBMmd3kYNoIs9dG-3q1HWFWN9ZNAEQ5oOvrWUqPx7vAmFYLtex5EyJ2q1jJ2IXMbf1DJpArttZekSI1lnLcB0xVonBcH0G7kgwr_mUXMY5QKsoK3uiWKKMGfNTHlg7NSlgvcpQAMLfJ2arm5t-G64

在开发加密解密数据的时候碰到需要把加密好的 byte 数组转换成 String 对象用于网络传输的需求,如果把字节数组直接转换成 UTF-8 等编码方式的话肯定会存在某些编码没有对应的字符,在传输过程中会遗漏数据。这时就可以通过常用的二进制数据编码方式 Base64 编码或者 Hex 编码来实现。

Hex编码

因为一个字节中存在8个 bit可以表示256个字符,而 ASCII 码只能表示0-127种字符,为了能完整地表示一个字节,可以将二进制数据转换为十六进制数据的方式来实现。所以 Hex 编码也被称作为 Base16 编码,相比于原先8位表示一个字节,Hex 编码能够只用2位表示一个字节。Hex 编码最常用于二进制文件查看时展示的编码,如 Hex Fiend 就可以支持查看二进制文件。

Base64编码

Base64编码是通过64个字符来表示二进制数据,64个字符表示二进制数据只能表示6位,所以他可以通过4个 Base64 的字符来表示3个字节,如下是 Base64 的字符编码表

举个 Base64 编码的例子,如要表示字符串 Man ,先将各个字符转换为二进制形式,也就是 01001101 01100001 01101110,再以6位为单位进行分割,如果表示的字符串长度不为3的倍数,也就是存在缺位时则以0填充。得到各个部分的十进制表示为19,22,5,46,依照这个索引可以得出对应的 Base64 字符,为T,W,F,u。

像下面字符串长度不为3的倍数时,Base64编码会出现=。

Base64 编码使用4个字符便能表示3个字节,也就是会冗余出1/3的长度,不过其作为压缩比较高以及简单的编码方式能够广泛运用于网络传播的密钥文件等的编码,有时甚至可以直接来表示小的图片,音频文件。Base64常被误用于数据加密,其实只要看到数据末尾是否有=符号就能判别是否使用了 Base64 加密便破解出来。只有不能被快速计算破解出来的数据加密方式才是严格意义上的加密。

______________________________________________________

参考:https://syaning.github.io/go-pkgs/encoding/hex.html  就读复旦大学

 

package main

import (
    "encoding/hex"
    "fmt"
)

func main() {
    msg := []byte("Hello 世界")

    encoded := hex.EncodeToString(msg)
    fmt.Println(encoded)
    // 48656c6c6f20e4b896e7958c

    //encoded = "4769676162697445746865726E6574302F302F323400"
    decoded, _ := hex.DecodeString(encoded)
    fmt.Println(string(decoded))
    // Hello 世界
}

  -------------------------------------------------------------

原文: https://www.cnblogs.com/iCanhua/p/8929988.html

深入编码本质】浅谈编码Base64、Hex、UTF-8、Unicode、GBK等

 

前言:

  网络上大多精彩的回答,该随笔用作自我总结;

  首先计算机只认得二进制,0和1,所以我们现在看到的字都是经过二进制数据编码后的;计算机能针对0和1的组合做很多事情,这些规则都是人定义的;然后有了字节的概念,8比特一个字节,如01011100就是一个字节;

  人定义好计算机的0和1的数据结构做事的时候,如果每个人都用不同的数据结构,不同的定义,就会使得人和人之间让计算机做的事无法统一,也导致无法通讯,所以要一起共同定义一套大家都认同的规则,其中ASCii码就是最初始的交换码,用做记录信息、交互信息的;

  相同的字节串不同的编码就会有不同的展示,只有正确的编码才能表达出字符串本身要记载的信息,而信息是面向人的,只有人能识别,才叫信息,只是偶尔被计算机理解;

字节、字符与字符串:

  字节是8比特位构成,上传已经说了;

  字符是用字节构成的,但多少字节,怎么构成我们认识的唯一的字符?这个由编码格式决定,也就是Unicode、GBK,(为啥要用字节?,因为历史觉得8比特很牛逼啊)

  字符串是字符的序列,各种计算机语言不同表示,如Redis就和C的字符串不一样,C是以 ‘\0’ 结尾;我们说的对字符的编码,而不是字符串;

Hex用字符串形式看二进制代码:

  首先,二进制文件通常不易于人看,因为人会看眼花,所以必须转为其他进制,16进制是最好的,刚好2字符表示一个字节

  Hex编码是以4比特作为一个单位编码,用4是因为计算机进位是2的倍数,而为了能把比特串分割开来,最适中就是取16进制;所以Hex编码就是16进制编码;用于人类比用比特更直观简介的方式看待比特串(马上反应过来比特串),当然取更多位不适合人口算;

  然后我们就有了WinHex这个工具的命名;用它修复二进制文件很不错,前提你对该文件二进制构表(一般是具有协议去解析二进制的,我称之为构表协议吧)很熟;

  Base64是面向网络的,其实性质也是这样;

Unicode、GBK都是字符串编码:

  看到知乎一个alipay的说啥编码和编码格式不同,gbk是unicode的编码格式,简直笑死人;

  Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。目前的Unicode字符分为17组编排,0x0000 至 0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1114112个,但是码表和字符串的映射可以用数字表示,高位填0,但编码的方案确实可以多种的,例如如果码数1,用2字节就是:0x0001,需要传输2字节;但有必要吗?明显是没必要的!

  重复一遍,字符是独一无二的,人类符号系统抽象的产物,世界唯一,全世界的字符构成字符集,字符也是在演进的;而Unicode和GBK等都是字符的一种编码;也就是一个二进制比特串(数字)和字符的映射表;

面向字符、面向字节

  对于一个抽象字符,在Java中的二进制表示当然需要编码,用的就是Unicode,如果源文件存储并非Unicode怎么办呢?当然需要转换,因此Java很多面向字符流的I/O其实都是默认有转换规则存在;

  这里提下I/O都分面向字节和字符,其实面向字节就是不管编码,而面向字符是带编码转换,是的一个抽象字符串如 “饭” 是在哪种编码格式都表示 “饭”,因此面向字符I/O指定编码格式很重要,一般不指定采用默认,如win操作系统默认GBK,而linux默认UTF-8;

UTF-8是编码规则 — 哈夫曼编码:

  Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。目前的Unicode字符分为17组编排,0x0000 至 0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1114112个,谨记;

  所以我们上面提到了,其实0x0001是没有必要用2个字节表示的,其实我用一个字节也可以的,那么什么情况下可以做到,在读一个2个字节表示的字符时候,我就读比特串中的2个字节位呢;所以比特串中,就需要有前几位代表,到底需要读几位;

  哈夫曼编码转换的

    Unicode

  UTF-8

  范围:0000 - 007F  前缀:0xxxxxxx

  范围:0080 - 07FF  前缀:110xxxxx 10xxxxxx

  范围:0800 - FFFF  前缀:1110xxxx 10xxxxxx 10xxxxx

  所以UTF-16也是一种编码规则,他们各自有各自的好处,主要体现在空间的节省上,如果文档的大部分字符串都是英文,那么用UTF-8会比较好,而如果大部分都是中文,则UTF-16会更节省空间。

-------------------------------- 优秀、是一种习惯 、、、、、、、、、、、、、、、
posted @ 2021-01-04 14:09  立志做一个好的程序员  阅读(8057)  评论(0编辑  收藏  举报

不断学习创作,与自己快乐相处