为了账号安全,请及时绑定邮箱和手机立即绑定

如何连续附加到 Go 中的 JSON 文件?

如何连续附加到 Go 中的 JSON 文件?

Go
慕姐4208626 2022-12-19 14:12:01
我想知道如何在 Go 中连续写入同一个文件?我必须使用os.WriteAt()吗?JSON 基本上只是一个充满结构的数组:[    {        "Id": "2817293",        "Data": "XXXXXXX"    },    {        "Id": "2817438",        "Data": "XXXXXXX"    }    ...]我想要连续向它添加正确的数据,即在关闭文件之前多次附加到该 JSON 数组。我要写入文件的数据是所述结构的一部分:dataToWrite := []struct{    Id   string    Data string}{}在 Go 中连续写入 JSON 数组的正确方法是什么?我当前的方法在 JSON 文件中创建多个切片,因此不是我想要的。写入过程(位于 for 循环中)如下所示:...            // Read current state of file            data := []byte{}            f.Read(data)            // Write current state to slice            curr := []Result{}            json.Unmarshal(data, &curr)            // Append data to the created slice            curr = append(curr, *initArr...)            JSON, _ := JSONMarshal(curr)            // Empty data container            initArr = &[]Result{}            // Write            _, err := f.Write(JSON)            if err != nil {                log.Fatal(err)            }...
查看完整描述

3 回答

?
拉莫斯之舞

TA贡献1820条经验 获得超10个赞

将开头写入[文件。在文件上创建一个编码器。遍历切片和每个切片的元素。如果它不是第一个切片元素,请写一个逗号。使用编码器对每个切片元素进行编码。写结尾]。


_, err := f.WriteString("[")

if err != nil {

    log.Fatal(err)

}


e := json.NewEncoder(f)

first := true

for i := 0; i < 10; i++ {


    // Create dummy slice data for this iteration.


    dataToWrite := []struct {

        Id   string

        Data string

    }{

        {fmt.Sprintf("id%d.1", i), fmt.Sprintf("data%d.1", i)},

        {fmt.Sprintf("id%d.2", i), fmt.Sprintf("data%d.2", i)},

    }


    // Encode each slice element to the file

    for _, v := range dataToWrite {


        // Write comma separator if not the first.

        if !first {

            _, err := f.WriteString(",\n")

            if err != nil {

                log.Fatal(err)

            }

        }

        first = false


        err := e.Encode(v)

        if err != nil {

            log.Fatal(err)

        }

    }

}

_, err = f.WriteString("]")

if err != nil {

    log.Fatal(err)

}

https://go.dev/play/p/Z-T1nxRIaqL


如果将所有 slice 元素保存在内存中是合理的,则通过在单个批次中对所有数据进行编码来简化代码:


type Item struct {

    Id   string

    Data string

}


// Collect all items to write in this slice.

var result []Item


for i := 0; i < 10; i++ {

    // Generate slice for this iteration.

    dataToWrite := []Item{

        {fmt.Sprintf("id%d.1", i), fmt.Sprintf("data%d.1", i)},

        {fmt.Sprintf("id%d.2", i), fmt.Sprintf("data%d.2", i)},

    }


    // Append slice generated in this iteration to the result.

    result = append(result, dataToWrite...)

}


// Write the result to the file.

err := json.NewEncoder(f).Encode(result)

if err != nil {

    log.Fatal(err)

}

https://go.dev/play/p/01xmVZg7ePc


查看完整回答
反对 回复 2022-12-19
?
精慕HU

TA贡献1845条经验 获得超8个赞

如果您不关心现有文件,您可以Encoder.Encode像@redblue 提到的那样在整个切片上使用。

如果您有一个要附加到的现有文件,最简单的方法是执行您在编辑中显示的内容:UnmarshalDecoder.Decoder将整个文件放入一个结构片中,将新结构附加到该片中,然后重新解码大量使用Marshalor Encoder.Encode

如果你有大量的数据,你可能要考虑使用JSON Lines来避免拖尾,]问题,并且每行写一个 JSON 对象。或者,您可以使用常规 JSON,从文件末尾向后查找,这样您就可以覆盖 final ],然后编写一个,,新的 JSON 编码结构,最后编写一个,]使文件再次成为有效的 JSON 数组。

因此,这在一定程度上取决于您的用例和您采用哪种方法的数据大小。


查看完整回答
反对 回复 2022-12-19
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

注意

这个答案是一个solution或者workaround如果你关心现有文件的内容!

这意味着它允许您附加到existing json由您创建的文件API。


显然这只适用于相同结构的数组


实际工作的 json 格式:


[

object,

...

object,

]

写入文件时,不要写[and ]。只需附加到写入序列化json对象的文件并附加一个,


实际文件内容:


object,

...

object,

最后在读取文件时[添加和追加]


这样你就可以write从多个来源访问文件并且仍然有效JSON


还要加载文件并为您的处理器提供有效输入json。


我们像这样编写日志文件并json通过REST调用提供一个 vaild,然后对其进行处理(例如通过 a JavaScript Grid)


查看完整回答
反对 回复 2022-12-19
  • 3 回答
  • 0 关注
  • 237 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号