2017-04-18 205 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() 
} 
相关问题