如何在 golang 中将 UUID 原始 16 字节写入 CSV?
Howto write UUID raw 16 bytes to CSV in golang?
我有以下代码,尝试将 UUID 原始 16 字节(内部包含 0x0A)保存为 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
为什么 encoding/csv 在我的字符串超出范围时添加额外的字节(参见 https://golang.org/src/encoding/csv/writer.go#L38, https://golang.org/src/encoding/csv/writer.go#L50 and https://golang.org/src/encoding/csv/writer.go#L76)?
谁能帮我找到不做奇怪转换的CSV包??
这是因为 CSV 格式不适合存储原始二进制数据,这不太可能是有效的 utf-8 序列。
发生的事情是,当csv_writer.Write
iterates 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。
我有以下代码,尝试将 UUID 原始 16 字节(内部包含 0x0A)保存为 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
为什么 encoding/csv 在我的字符串超出范围时添加额外的字节(参见 https://golang.org/src/encoding/csv/writer.go#L38, https://golang.org/src/encoding/csv/writer.go#L50 and https://golang.org/src/encoding/csv/writer.go#L76)?
谁能帮我找到不做奇怪转换的CSV包??
这是因为 CSV 格式不适合存储原始二进制数据,这不太可能是有效的 utf-8 序列。
发生的事情是,当csv_writer.Write
iterates 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。