英文:
Go. Writing []byte to file results in zero byte file
问题
我试图将结构化数据序列化到文件中。我查看了一些示例,并创建了以下结构:
func (order Order) Serialize(folder string) {
b := bytes.Buffer{}
e := gob.NewEncoder(&b)
err := e.Encode(order)
if err != nil { panic(err) }
os.MkdirAll(folder, 0777)
file, err := os.Create(folder + order.Id)
if err != nil { panic(err) }
defer file.Close()
writer := bufio.NewWriter(file)
n, err := writer.Write(b.Bytes())
fmt.Println(n)
if err != nil {
panic(err)
}
}
Serialize
是一个将对象序列化到文件中的方法,通过它的 id 属性调用。我查看了调试器 - 字节缓冲区在写入之前包含数据。我的意思是对象已经完全初始化。即使表示写入字节数的 n
变量超过一千 - 文件也不应该是空的。文件被创建了,但是完全为空。有什么问题吗?
英文:
I try to serialize a structured data to file. I looked through some examples and made such construction:
func (order Order) Serialize(folder string) {
b := bytes.Buffer{}
e := gob.NewEncoder(&b)
err := e.Encode(order)
if err != nil { panic(err) }
os.MkdirAll(folder, 0777)
file, err := os.Create(folder + order.Id)
if err != nil { panic(err) }
defer file.Close()
writer := bufio.NewWriter(file)
n, err := writer.Write(b.Bytes())
fmt.Println(n)
if err != nil {
panic(err)
}
}
Serialize
is a method serializing its object to file called by it's id property. I looked through debugger - byte buffer contains data before writing. I mean object is fully initialized. Even n
variable representing quantity of written bytes is more than a thousand - the file shouldn't be empty at all. The file is created but it is totally empty. What's wrong?
答案1
得分: 4
bufio.Writer
(正如包名所示)使用缓冲区来缓存写入操作。如果你使用它,必须在完成写入操作后调用Writer.Flush()
来确保缓冲数据被写入底层的io.Writer
。
另外请注意,你可以直接向os.File
写入,无需创建一个“包装”它的缓冲写入器(*os.File
实现了io.Writer
)。
还要注意,你可以直接将gob.Encoder
创建为指向os.File
的,因此bytes.Buffer
是不必要的。
此外,os.MkdirAll()
可能会失败,请检查其返回值。
另外,最好使用filepath.Join()
来“连接”文件路径的各个部分,它会处理文件夹名称末尾的额外斜杠或缺失斜杠的情况。
最后,最好通过返回一个error
值来表示Serialize()
的失败,这样调用方有机会检查操作是否成功,并采取相应的措施。
因此,Order.Serialize()
应该如下所示:
func (order Order) Serialize(folder string) error {
if err := os.MkdirAll(folder, 0777); err != nil {
return err
}
file, err := os.Create(filepath.Join(folder, order.Id))
if err != nil {
return err
}
defer file.Close()
if err := gob.NewEncoder(file).Encode(order); err != nil {
return err
}
return nil
}
英文:
bufio.Writer
(as the package name hints) uses a buffer to cache writes. If you ever use it, you must call Writer.Flush()
when you're done writing to it to ensure the buffered data gets written to the underlying io.Writer
.
Also note that you can directly write to an os.File
, no need to create a buffered writer "around" it. (*os.File
implements io.Writer
).
Also note that you can create the gob.Encoder
directly directed to the os.File
, so even the bytes.Buffer
is unnecessary.
Also os.MkdirAll()
may fail, check its return value.
Also it's better to "concatenate" parts of a file path using filepath.Join()
which takes care of extra / missing slashes at the end of folder names.
And last, it would be better to signal the failure of Serialize()
, e.g. with an error
return value, so the caller party has the chance to examine if the operation succeeded, and act accordingly.
So Order.Serialize()
should look like this:
func (order Order) Serialize(folder string) error {
if err := os.MkdirAll(folder, 0777); err != nil {
return err
}
file, err := os.Create(filepath.Join(folder, order.Id))
if err != nil {
return err
}
defer file.Close()
if err := gob.NewEncoder(file).Encode(order); err != nil {
return err
}
return nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论