我有一个包含几个大型XML文件的目录(总大小约为10 GB)。有什么方法可以遍历包含XML文件的目录并读取50字节乘50字节并以高性能解析XML文件吗?
func (mdc *Mdc) Loadxml(path string, wg sync.WaitGroup) {
defer wg.Done()
//var conf configuration
file, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
buf := make([]byte, 1024*1024)
scanner.Buffer(buf, 50)
for scanner.Scan() {
_, err := file.Read(buf)
if err != nil {
log.Fatal(err)
}
}
err = xml.Unmarshal(buf, &mdc)
if err != nil {
log.Fatal(err)
}
fmt.Println(mdc)
}
Run Code Online (Sandbox Code Playgroud)
您可以做得更好:您可以标记您的 xml 文件。
假设你有一个像这样的 xml
<inventory>
<item name="ACME Unobtainium">
<tag>Foo</tag>
<count>1</count>
</item>
<item name="Dirt">
<tag>Bar</tag>
<count>0</count>
</item>
</inventory>
Run Code Online (Sandbox Code Playgroud)
你实际上可以拥有以下数据模型
type Inventory struct {
Items []Item `xml:"item"`
}
type Item struct {
Name string `xml:"name,attr"`
Tags []string `xml:"tag"`
Count int `xml:"count"`
}
Run Code Online (Sandbox Code Playgroud)
现在,您所要做的就是使用filepath.Walk并对要处理的每个文件执行类似的操作:
decoder := xml.NewDecoder(file)
for {
// Read tokens from the XML document in a stream.
t, err := decoder.Token()
// If we are at the end of the file, we are done
if err == io.EOF {
log.Println("The end")
break
} else if err != nil {
log.Fatalf("Error decoding token: %s", err)
} else if t == nil {
break
}
// Here, we inspect the token
switch se := t.(type) {
// We have the start of an element.
// However, we have the complete token in t
case xml.StartElement:
switch se.Name.Local {
// Found an item, so we process it
case "item":
var item Item
// We decode the element into our data model...
if err = decoder.DecodeElement(&item, &se); err != nil {
log.Fatalf("Error decoding item: %s", err)
}
// And use it for whatever we want to
log.Printf("'%s' in stock: %d", item.Name, item.Count)
if len(item.Tags) > 0 {
log.Println("Tags")
for _, tag := range item.Tags {
log.Printf("\t%s", tag)
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用虚拟 XML 的工作示例: https: //play.golang.org/p/MiLej7ih9Jt