go语言解析INI文件

RTFSC · · 2575 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
package main
 
 import (
 	"bufio"
 	"bytes"
 	"io"
 	"os"
 	"unicode"
 )
 
 const (
 	stat_none = iota
 	stat_group
 	stat_key
 	stat_value
 	stat_comment
 )
 
 type Attr struct {
 	Name    string
 	Value   string
 	Comment string
 	next    *Attr
 }
 
 type Element struct {
 	Element string
 	Attr    *Attr
 	next    *Element
 }
 
 type Decoder struct {
 	state int
 	b     byte
 	t     bytes.Buffer
 	r     io.ByteReader
 	err   error
 	m     *Element
 	n     string
 }
 
 func (d *Decoder) getAttr(m *Element, e string) string {
 	for n := m.Attr; nil != n; n = n.next {
 		if e == n.Name {
 			return n.Value
 		}
 	}
 	return ""
 }
 
 func (d *Decoder) GetElement(e string, a string) string {
 	for n := d.m; nil != n; n = n.next {
 		if e == n.Element {
 			return d.getAttr(n, a)
 		}
 	}
 	return ""
 }
 
 func (d *Decoder) newAttrNextComment(value string) {
 	d.m.Attr.Comment = value
 	println(value)
 }
 
 func (d *Decoder) newAttrNext(name string, value string) {
 	attr := new(Attr)
 	attr.Name = name
 	attr.Value = value
 	if nil == d.m.Attr {
 		attr.next = nil
 	} else {
 		attr.next = d.m.Attr
 	}
 	d.m.Attr = attr
 }
 
 func (d *Decoder) newElement(name string) {
 	element := new(Element)
 	element.Element = name
 	element.Attr = nil
 	if nil == d.m {
 		element.next = nil
 	} else {
 		element.next = d.m
 	}
 	d.m = element
 }
 
 func (d *Decoder) switchToMap() {
 	for {
 		d.b, d.err = d.r.ReadByte()
 		if d.err != nil {
 			break
 		}
 		switch d.state {
 		case stat_none:
 			if d.b == '[' {
 				d.state = stat_group
 			} else if d.b == ';' {
 				d.state = stat_comment
 			} else if !unicode.IsSpace(rune(d.b)) {
 				d.state = stat_key
 				d.t.WriteByte(byte(d.b))
 			}
 			break
 		case stat_group:
 			if d.b == ']' {
 				d.state = stat_none
 				d.newElement(d.t.String())
 				d.t.Reset()
 			} else if !unicode.IsSpace(rune(d.b)) {
 				d.t.WriteByte(byte(d.b))
 			}
 			break
 		case stat_key:
 			if d.b == '=' {
 				d.state = stat_value
 				d.n = d.t.String()
 				d.t.Reset()
 			} else if !unicode.IsSpace(rune(d.b)) {
 				d.t.WriteByte(byte(d.b))
 			}
 			break
 		case stat_value:
 			if !unicode.IsSpace(rune(d.b)) {
 				d.t.WriteByte(byte(d.b))
 			} else {
 				d.state = stat_none
 				d.newAttrNext(d.n, d.t.String())
 				d.t.Reset()
 			}
 			break
 		case stat_comment:
 			if !unicode.IsSpace(rune(d.b)) {
 				d.t.WriteByte(byte(d.b))
 			} else {
 				d.state = stat_none
 				d.newAttrNextComment(d.t.String())
 				d.t.Reset()
 			}
 			break
 		default:
 			d.state = stat_none
 			break
 		}
 	}
 }
 
 func (d *Decoder) switchToReader(r io.Reader) {
 	if rb, ok := r.(io.ByteReader); ok {
 		d.r = rb
 	} else {
 		d.r = bufio.NewReader(r)
 	}
 	d.switchToMap()
 }
 
 func NewDecoder(r io.Reader) *Decoder {
 	d := &Decoder{}
 	d.switchToReader(r)
 	return d
 }
 
 func main() {
 	xmlFile, err := os.Open("hh.ini")
 	if nil != err {
 		return
 	}
 	defer xmlFile.Close()
 	d := NewDecoder(xmlFile)
 	println(d.GetElement("aaaa", "ac"))
 }
 

  

本文来自:博客园

感谢作者:RTFSC

查看原文:go语言解析INI文件

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:muxilin131420 备注:入群;或加QQ群:977810755

2575 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传