首页 文章

将换行符分隔的JSON blob的整个文件读取到内存中,并在golang中以最少的转换量解组每个blob?

提问于
浏览
1

我是新手,所以不太了解语言特定的结构 .

我的用例首先是在内存中读入一个包含J换命包的输入文件,这些命令是换行符分隔的 . 从JSON源的这个“数组”,我想解组每个数组元素来在golang中处理它 . 预期的结构映射已经定义 .

我通常喜欢一次读取所有行,所以How can I read a whole file into a string variable in Golang?中提到的 ioutil.ReadFile() 似乎是一个不错的选择 . 并且 json.Unmarshal 似乎将字节数组作为源 . 但是,如果我认为最好的技术是不喜欢优化的方法但不确定如何解决go中的实现算法细节,可以在这里使用一些提示 .

理想情况下,我希望事先完成预处理,这样我就不会处理来自文件的JSON字节数组的内容,因为我正在遍历切片等等 . 而是我想预处理单字节数组从文件读取到一个字节数组切片数组,删除所有换行字节,每个切片是由换行符分隔的段 .

1 回答

  • 6

    使用bufio.Scanner一次读取一行:

    f, err := os.Open(fname)
     if err != nil {
         // handle error
     }
     s := bufio.NewScanner(f)
     for s.Scan() {
        var v ValueTypeToUnmarshalTo
        if err := json.Unmarshal(s.Bytes(), &v); err != nil {
           //handle error
        }
        // do something with v
    }
    if s.Err() != nil {
        // handle scan error
    }
    

    或者使用ioutil.ReadFile来填充整个文件,并使用bytes.Split将文件分成几行:

    p, err := ioutil.ReadFile(fname)
     if err != nil {
        // handle error
     }
     for _, line := range bytes.Split(p, []byte{'\n'}) {
        var v ValueTypeToUnmarshalTo
        if err := json.Unmarshal(line, &v); err != nil {
           //handle error
        }
        // do something with v
     }
    

    或使用json.Decoder内置流功能从文件中读取多个值:

    f, err := os.Open(fname)
     if err != nil {
        // handle error
     }
     d := json.NewDecoder(f)
     for {
        var v ValueTypeToUnmarshalTo
        if err := d.Decode(&v); err == io.EOF {
           break // done decoding file
        } else if err != nil {
           // handle error
        }
        // do something with v
    }
    

    在操场上运行代码

    ioutil.ReadFile方法比其他方法使用更多内存(文件中每个字节一个字节加上每一行一个切片标头) .

    因为解码器忽略了遵循JSON值的空格,所以这三种方法处理\ r \ n行终止符 .

    除了将JSON字节解组为Go值所固有的方法之外,这些方法中没有任何数据转换 .

相关问题