2017-04-18 21 views
0

我試圖轉義golang字符串中的特定十六進制值。函數調用看起來是這樣的:轉義字符串文字中的十六進制值

Insert(0, "\x00\x00\x00\rIHDR\x00\x00\x000\x00\x00\x000\b\x03") 
Insert(25, "\x00\x00\x00\x06PLTE") 
Insert(43, "\x00\x00\x00\x02tRNS") 
Insert(57, "\x00\x00\t;IDATx\xDA\x010\t\xCF\xF6") // problem line 
Insert(2432, "\x00\x00\x00\x00IEND") 

時,語言解釋「\ XDA」十六進制轉義的問題就出現了。而不是正確地轉義到一個Ú值,它被轉義爲Replace(替換字符)。

我保證這是什麼存在的在下面的操場例如:

fmt.Println("\xDA") 
i := 218 
h := fmt.Sprintf("%x", i) 
fmt.Printf("Hex conf of '%d' is '%s'\n", i, h) 
fmt.Println(string(i)) 

這個片段中,在運行時,打印

� 
Hex conf of '218' is 'da' 
Ú 

我在這裏失去了一些東西? 「\ xDA」正在被轉移到65533的值的事實是拋棄了我的整個程序,該程序依賴於CRC32和其他一些校驗和。這不會發生在這個程序的javascript version(它本身是從James compface程序的翻譯,用C編寫)。

這裏是操場鏈接:https://play.golang.org/p/c-XMK68maX

+0

'\ xDA' _is_一個有效的十六進制轉義。 '符文(218)'的utf8編碼是'\ xc3 \ x9a'。我不確定你期望在這裏發生什麼。 – JimB

+0

我可能會誤解,但我期待'fmt.Println(「\ xDA」)'輸出'Ú'而不是' ' –

回答

3

圍棋串都只是一系列的字節數,但需要編碼的時候,它的假設是UTF8。值\xda是不是一個有效的UTF8字符,所以打印時它轉換爲unicode.ReplacementCharacter「」

ReplacementChar = '\uFFFD'  // Represents invalid code points. 

如果你想的\xda在字符串中的符文值文字,使用Unicode轉義:\u00DA,或使用utf8編碼:\xc3\x9a,或使用字符本身:Ú

https://play.golang.org/p/EJZIqCI_Gr

如果你確實想在你的字符串\xda一個字節值,也就是你有什麼和印刷字符是無關緊要的。

+0

謝謝!我剛剛結束了將十六進制值更改爲unicode(幾分鐘後),並從那裏順利進行;) –

1

您的輸入看起來像ISO-8859-1(Latin-1的)。將其轉換爲UTF-8。例如,

package main 

import (
    "fmt" 
    "unicode/utf8" 
) 

// ISO88591ToString maps ISO-8859-1 (Latin-1) to string (UTF-8). 
func ISO88591ToString(iso string) string { 
    var utf []rune 
    for i := 0; i < len(iso); i++ { 
     r := iso[i] 
     if utf == nil { 
      if r < utf8.RuneSelf { 
       continue 
      } 
      utf = make([]rune, len(iso)) 
      for j, r := range iso[:i] { 
       utf[j] = rune(r) 
      } 
     } 
     utf[i] = rune(r) 
    } 
    if utf == nil { 
     return string(iso) 
    } 
    return string(utf) 
} 

func main() { 
    l1 := "\x00\x00\t;IDATx\xDA\x010\t\xCF\xF6" 
    fmt.Printf("%q\n", l1) 
    s := ISO88591ToString(l1) 
    fmt.Printf("%q\n", s) 
} 

輸出:

"\x00\x00\t;IDATx\xda\x010\t\xcf\xf6" 
"\x00\x00\t;IDATxÚ\x010\tÏö" 
1

Go中的字符串是UTF-8,而\xDA本身並不是一個有效的UTF-8序列,意味着將它打印爲字符串的一部分將會產生Unicode替換字符U + FFFD而不是您想要的Ú或U + 00DA)。

但是,您似乎正在處理原始字節,所以您應該考慮是否需要用UTF-8編碼爲\u00DA的符號作爲2字節的序列\xC3\x8F,或者是否需要單字節\xDA。前者將根據需要打印Ú,需要2個字節。後者不會像您期望的那樣打印,但它會正確地將\xDA解釋爲1個字節而不是2個字節。

下面是一個說明性的例子,你可以run on the Playground

func main() { 
    // A string made up of UTF-8 lead bytes. 
    dataString := "\xCF\xDA\xF6" 

    // Doesn't print what you think it should. 
    for _, c := range dataString { 
     fmt.Printf("%X ", c) 
    } 
    fmt.Println() 

    // Convert the string's bytes to a byte slice. 
    data := []byte(dataString) 

    // Now it should print CF, DA, F6. 
    for _, b := range data { 
     fmt.Printf("%X ", b) 
    } 
    fmt.Println() 
} 
相關問題