我想要从不同的文本或JSON或CSV文件中读取数据。我应该采用哪种方法?
我有关于文件读取的博客文章File read和Read 2 GB text file with small RAM,介绍了不同的文件读取方法。
不同的方法:
- 分块读取文件
- 并发地读取文件块
- 将整个文件读入内存
- 将长字符串拆分为单词
- 逐个单词扫描
什么是在小内存情况下读取文件的最快方法?
我想要从不同的文本或JSON或CSV文件中读取数据。我应该采用哪种方法?
我有关于文件读取的博客文章File read和Read 2 GB text file with small RAM,介绍了不同的文件读取方法。
什么是在小内存情况下读取文件的最快方法?
基本上有两种不同的方法来解析文件:文档解析和流解析。
文档解析读取文件中的数据并将其转换为一组大型对象,您可以像浏览器中的HTML DOM一样查询这些对象。优点是您可以随时获取完整的数据,这通常更简单。缺点是您必须将所有数据存储在内存中。
dom = parse(stuff)
// Now do whatever you like with the DOM
for element := range stream(stuff) {
...examine one element at a time...
}
幸运的是,Go提供了处理常见格式的库。
一个简单的例子是处理CSV文件。
package main
import(
"encoding/csv"
"fmt"
"log"
"os"
"io"
)
func main() {
file, err := os.Open("test.csv")
if err != nil {
log.Fatal(err)
}
parser := csv.NewReader(file)
...
}
[][]string
读入内存。records, err := parser.ReadAll()
if err != nil {
log.Fatal(err)
}
for _,record := range records {
fmt.Println(record)
}
或者我们可以节省大量内存,一次处理一行。
for {
record, err := parser.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
fmt.Println(record)
}
由于CSV的每一行都具有相同的功能,逐行处理是最合理的。
JSON和XML比较复杂,因为它们是大型嵌套结构,但也可以进行流式处理。在encoding/json文档中有流式处理的示例。
records := make( chan []string )
go func() {
parser := csv.NewReader(file)
defer close(records)
for {
record, err := parser.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
records <- record
}
}();
func print_records( records chan []string ) {
for record := range records {
fmt.Println(record)
}
}