2017-04-18 17 views
0

golang文字列の特定の16進値をエスケープしようとしています。関数呼び出しは次のようになります。文字列リテラルの16進数値のエスケープ

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」進エスケープを解釈するときに問題が発生します。正しくÚ値にエスケープする代わりに、 (置換文字)にエスケープされます。

私は、これは以下の遊び場例でoccuringたものである保証:、

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にありません(それ自体はCで書かれたJames compfaceプログラムの翻訳です)。ここで

は、遊び場のリンクです:https://play.golang.org/p/c-XMK68maX

+0

'\ xDA'は有効な16進エスケープを_is_。 'rune(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

ありがとう!私はちょうどユニコード(ポストの数分後に)に16進値を変更して終了し、すべてがスムーズにそこから行った;) –

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)。

あなたはしかし、生のバイトで働いているように見えるので、あなたは2バイトのシーケンス\xC3\x8FとしてUTF-8でエンコードされ\u00DAで表さルーンを、かどうかを検討すべきである、またはあなたが1バイトを必要とするかどうか\xDA。前者は2バイトが必要であることを注意しながらÚを印刷します。後者は期待どおりに印刷されませんが、正しく解釈されるのは\xDAで、2バイトではなく1バイトと解釈されます。ここで

はあなたが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() 
} 
関連する問題