2017-04-16 42 views
0

我有以下的代码,它尝试UUID生16个字节(带的0x0A内)保存到CSV格式如何在UML中将UUID原始16字节写入CSV?

package main 

import (
    "encoding/csv" 
    "github.com/satori/go.uuid" 
    "log" 
    "os" 
) 

func main() { 
    u, err := uuid.FromString("e1393c62-877a-4adc-8ffb-f1bf0a337c5f") 
    if err != nil { 
     log.Fatal(err) 
    } 
    csv_file, err := os.OpenFile("csv_wtf.csv", os.O_WRONLY|os.O_CREATE, 0644) 
    if err != nil { 
     log.Fatal(err) 
    } 
    s := string(u.Bytes()) 
    log.Printf("len(s)=%d",len(s)) 
    csv_writer := csv.NewWriter(csv_file) 
    csv_writer.UseCRLF = false 
    csv_writer.Write([]string{s}) 
    csv_writer.Flush() 
    finfo, err := csv_file.Stat() 
    if err != nil { 
     log.Fatal(err) 
    } 
    log.Printf("size csv_wtf.csv = %d", finfo.Size()) 
    csv_file.Close() 
} 

这段代码的输出数据为CSV与添加额外的字节

2017/04/16 12:37:14 len(s)=16 
2017/04/16 12:37:14 size csv_wtf.csv = 29 

为什么编码/ CSV当我的字符串超过范围时添加额外的字节(请参阅https://golang.org/src/encoding/csv/writer.go#L38,https://golang.org/src/encoding/csv/writer.go#L50https://golang.org/src/encoding/csv/writer.go#L76)?

有人可以帮我找到CSV包不会奇怪的转换吗?

+0

CSV文件中的数据看起来像什么,看起来像什么。通过观察长度,很难看到会发生什么。 –

+0

我需要在https://github.com/yandex/clickhouse数据库中插入FixedString(16)优化的UUID存储 – Slach

回答

3

这是因为CSV格式不适合存储原始二进制数据,这不太可能是有效的utf-8序列。

什么情况是,当csv_writer.Writeiterates a string with range loop,每次它遇到了无效的UTF-8序列,所述符r1变得等于65533,它被编码为3个字节:0xef, 0xbf, 0xbd

说明性实例:

package main 

import (
    "bytes" 
    "fmt" 
) 

func main() { 
    invalidString := string([]byte{0xff, 0xfe, 0xfd}) 
    var b bytes.Buffer 
    for _, r := range invalidString { 
     fmt.Printf("current rune: %v\n", r) 
     b.WriteRune(r) 
    } 

    fmt.Printf("total data: %v\n", b.Bytes()) 
} 

的输出是:

current rune: 65533 
current rune: 65533 
current rune: 65533 
total data: [239 191 189 239 191 189 239 191 189] 

所以就应该把有利于某些其他格式的放弃CSV(适合于存储二进制数据)中,或者商店的UUID其字符串形式。