1. 程式人生 > 其它 >Golang中的空字元,似花不是花

Golang中的空字元,似花不是花

  最近在Linux下開發Go程式,發現一個奇怪的問題,在讀取Linux系統資訊時讀到了空字元,導致了程式異常。在ASSIC中十六進位制0為字元NUT,表示為字元NULL。但這個字元在不同的程式語言、不同的執行環境中卻有著不一樣的呈現,如果換一個角度看,空字元也就是無字元也就能解釋ASSIC空字元沒有顯示了。
  在ASSIC中雖然十進位制0-31、127為控制字元但各自的表現形式不一樣,比較常用的字元:如換行\n、製表符\t等表現較為明顯,空字元算較為特殊的。
  似花不是花的只是一種錯覺,似它不是它;
  6461746100為ASSIC碼的十六進位制表示,字元為dataNUT,下面使用Go與Java分別在Windows與Ubnuntu環境

下看其表示形式。

Go

  在Golang中不同平臺有著不一樣的呈現效果,windows環境下可看得見,NUT空字元但在Linux環境下卻是不可見的。
  程式碼如下:

 buf,_:=hex.DecodeString("6461746100")
 s:=string(buf)
 fmt.Println(fmt.Sprintf("%v|長度:",s))

  Ubuntu環境下IDEA的debug模式,輸出為:data|長度:5

Windows環境下輸出:

字元處理

  空字元不是空格,空字元的ASSIC十六進位制為0,空格的十六進位制為32,字串中兩者的處理也不相同;空格與空字串是比較容易混淆的兩個字元;
  在字串的處理:查詢、替換、移除等操作中也比較容易把這兩者混淆。

buf,_:=hex.DecodeString("6461746100")   s:=string(buf)
ss:=strings.Trim(s, "\000")                //移除空字元
st:=strings.TrimFunc(s, func(r rune) bool {  //移除空字元       
  return r==0
})
i:=strings.IndexRune(s,0)        //查詢空字元索引
exist:=strings.Contains(s, "\x00")  //查詢空字元

  如上程式碼想要替換字串中的空字元,必須使用字元或轉義符進行;轉義符有兩種形式,八進位制轉義符與十六進位制轉義符,八進位制轉義符格式為:\DDD,十六進位制轉義符格式為:\xDD,DD為具體代表的ASSIC碼數字,Unicode轉義符:\uDDDD。

Java

  原以為在Java中並不存在這種問題,比較符合直覺,空字元就是空字元,但實際上與Go一樣在不同平臺也有不一樣的顯示效果,好在Java在IDEA中還是能夠看得到其字串內部的字元資訊,可以明顯的看得到空字元的存在。
如下程式碼。

byte[] bytes=Hex.decodeHex("6461746100");
String n=new String(bytes);
System.out.println(String.format("%s|,長度:%s",n,n.length()));

  Windows中現在還比較正常,符合人類認知,將byte陣列轉為字串是可明顯看到有一個空字元存在,在不管是在debug時還是程式列印輸出,都輸出了空字串;

程式輸出為:data |,長度:5

  在Linux環境下,此時n字串已經看不到空字元了,雖然內部字元陣列中依然看得到空字元的存在,但輸出已經看不到空字元的存在。

程式輸出:data|,長度:5


文章首發地址:https://mp.weixin.qq.com/s/4H-yEBkhTe9KVChQaNiP5w