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("界"))) }
----------------------------------------------------------
在開發加密解密數據的時候碰到需要把加密好的 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會更節省空間。