iniutils for Golang
一直有计划将 Delphi 中的譬如 TIniFile 等相关功能移植到 Golang,这些设施在 Delphi 中(相对而言)比较常用,使用起来也非常方便。
虽然 Github 上早已有这些三方库,但我还是想仿照 Delphi 的做法来实现一套(其实只是模仿了 TMemIniFile 而非 Windows 下的 TIniFile 实现,暂时无意愿去实现 GetPrivateProfileXXX/WritePrivateProfileXXX 等 API),并额外提供直接干脆的调用接口等。
代码已托管至 Github。
// Copyright 2017 ecofast(无尽愿). All rights reserved.
// Use of this source code is governed by a BSD-style license. // Package iniutils was translated from TMemIniFile in Delphi(2007) RTL,
// which loads an entire INI file into memory
// and allows all operations to be performed on the memory image.
// The image can then be written out to the disk file.
package iniutils import (
"bufio"
"bytes"
"fmt"
"os"
"strconv"
"strings" "github.com/ecofast/sysutils"
) type IniFile struct {
fileName string
caseSensitive bool
sections map[string][]string
} func NewIniFile(filename string, casesensitive bool) *IniFile {
ini := &IniFile{
fileName: filename,
caseSensitive: casesensitive,
sections: make(map[string][]string),
}
ini.loadValues()
return ini
} func (ini *IniFile) FileName() string {
return ini.fileName
} func (ini *IniFile) CaseSensitive() bool {
return ini.caseSensitive
} func (ini *IniFile) String() string {
var buf bytes.Buffer
for sec, lst := range ini.sections {
buf.WriteString(fmt.Sprintf("[%s]\n", sec))
for _, s := range lst {
buf.WriteString(fmt.Sprintf("%s\n", s))
}
buf.WriteString("\n")
}
return buf.String()
} func (ini *IniFile) getRealValue(s string) string {
if !ini.caseSensitive {
return strings.ToLower(s)
}
return s
} func (ini *IniFile) loadValues() {
if !sysutils.FileExists(ini.fileName) {
return
} file, err := os.Open(ini.fileName)
if err != nil {
return
}
defer file.Close() section := ""
scanner := bufio.NewScanner(file)
for scanner.Scan() {
s := scanner.Text()
s = strings.TrimSpace(s)
s = ini.getRealValue(s)
if s != "" && s[0] != ';' {
if s[0] == '[' && s[len(s)-1] == ']' {
s = s[1 : len(s)-1]
section = s
} else {
if section != "" {
if pos := strings.Index(s, "="); pos > 0 {
if sl, ok := ini.sections[section]; ok {
ini.sections[section] = append(sl, s)
} else {
ini.sections[section] = []string{s}
}
} else {
// ingore invalid ident
//
}
}
}
}
}
} func (ini *IniFile) flush() {
file, err := os.Create(ini.fileName)
sysutils.CheckError(err)
defer file.Close() fw := bufio.NewWriter(file)
for sec, lst := range ini.sections {
_, err = fw.WriteString(fmt.Sprintf("[%s]\n", sec))
sysutils.CheckError(err) for _, s := range lst {
_, err = fw.WriteString(fmt.Sprintf("%s\n", s))
sysutils.CheckError(err)
} _, err = fw.WriteString("\n")
sysutils.CheckError(err)
}
fw.Flush()
} func (ini *IniFile) SectionExists(section string) bool {
sec := ini.getRealValue(section)
if _, ok := ini.sections[sec]; ok {
return true
}
return false
} func (ini *IniFile) ReadSections() []string {
var ss []string
for sec, _ := range ini.sections {
ss = append(ss, sec)
}
return ss
} func (ini *IniFile) EraseSection(section string) {
sec := ini.getRealValue(section)
delete(ini.sections, sec)
} func (ini *IniFile) ReadSectionIdents(section string) []string {
var ss []string
sec := ini.getRealValue(section)
if sl, ok := ini.sections[sec]; ok {
for _, s := range sl {
if pos := strings.Index(s, "="); pos > 0 {
ss = append(ss, s[0:pos])
}
}
}
return ss
} func (ini *IniFile) ReadSectionValues(section string) []string {
var ss []string
sec := ini.getRealValue(section)
if sl, ok := ini.sections[sec]; ok {
for _, s := range sl {
ss = append(ss, s)
}
}
return ss
} func (ini *IniFile) DeleteIdent(section, ident string) {
sec := ini.getRealValue(section)
id := ini.getRealValue(ident)
if sl, ok := ini.sections[sec]; ok {
for i := 0; i < len(sl); i++ {
s := sl[i]
if pos := strings.Index(s, "="); pos > 0 {
if s[0:pos] == id {
var ss []string
for j := 0; j < i; j++ {
ss = append(ss, sl[j])
}
for j := i + 1; j < len(sl); j++ {
ss = append(ss, sl[j])
}
ini.sections[sec] = ss
return
}
}
}
}
} func (ini *IniFile) IdentExists(section, ident string) bool {
sec := ini.getRealValue(section)
id := ini.getRealValue(ident)
if sl, ok := ini.sections[sec]; ok {
for _, s := range sl {
if pos := strings.Index(s, "="); pos > 0 {
if s[0:pos] == id {
return true
}
}
}
}
return false
} func (ini *IniFile) ReadString(section, ident, defaultValue string) string {
sec := ini.getRealValue(section)
id := ini.getRealValue(ident)
if sl, ok := ini.sections[sec]; ok {
for _, s := range sl {
if pos := strings.Index(s, "="); pos > 0 {
if s[0:pos] == id {
return s[pos+1:]
}
}
}
}
return defaultValue
} func (ini *IniFile) WriteString(section, ident, value string) {
sec := ini.getRealValue(section)
id := ini.getRealValue(ident)
if sl, ok := ini.sections[sec]; ok {
for i := 0; i < len(sl); i++ {
s := sl[i]
if pos := strings.Index(s, "="); pos > 0 {
if s[0:pos] == id {
var ss []string
for j := 0; j < i; j++ {
ss = append(ss, sl[j])
}
ss = append(ss, ident+"="+value)
for j := i + 1; j < len(sl); j++ {
ss = append(ss, sl[j])
}
ini.sections[sec] = ss
return
}
}
}
ini.sections[sec] = append(sl, ident+"="+value)
} else {
ini.sections[sec] = []string{ident + "=" + value}
}
} func (ini *IniFile) ReadInt(section, ident string, defaultValue int) int {
s := ini.ReadString(section, ident, "")
if ret, err := strconv.Atoi(s); err == nil {
return ret
} else {
return defaultValue
}
} func (ini *IniFile) WriteInt(section, ident string, value int) {
ini.WriteString(section, ident, strconv.Itoa(value))
} func (ini *IniFile) ReadBool(section, ident string, defaultValue bool) bool {
s := ini.ReadString(section, ident, sysutils.BoolToStr(defaultValue))
return sysutils.StrToBool(s)
} func (ini *IniFile) WriteBool(section, ident string, value bool) {
ini.WriteString(section, ident, sysutils.BoolToStr(value))
} func (ini *IniFile) ReadFloat(section, ident string, defaultValue float64) float64 {
s := ini.ReadString(section, ident, "")
if s != "" {
if ret, err := strconv.ParseFloat(s, 64); err == nil {
return ret
}
}
return defaultValue
} func (ini *IniFile) WriteFloat(section, ident string, value float64) {
ini.WriteString(section, ident, sysutils.FloatToStr(value))
} func (ini *IniFile) Close() {
ini.flush()
} func (ini *IniFile) Clear() {
ini.sections = make(map[string][]string)
} func IniReadString(fileName, section, ident, defaultValue string) string {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadString(section, ident, defaultValue)
} func IniWriteString(fileName, section, ident, value string) {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
inifile.WriteString(section, ident, value)
} func IniReadInt(fileName, section, ident string, defaultValue int) int {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadInt(section, ident, defaultValue)
} func IniWriteInt(fileName, section, ident string, value int) {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
inifile.WriteInt(section, ident, value)
} func IniSectionExists(fileName, section string) bool {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.SectionExists(section)
} func IniReadSectionIdents(fileName, section string) []string {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadSectionIdents(section)
} func IniReadSections(fileName string) []string {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadSections()
} func IniReadSectionValues(fileName, section string) []string {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.ReadSectionValues(section)
} func IniEraseSection(fileName, section string) {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
inifile.EraseSection(section)
} func IniIdentExists(fileName, section, ident string) bool {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
return inifile.IdentExists(section, ident)
} func IniDeleteIdent(fileName, section, ident string) {
inifile := NewIniFile(fileName, false)
defer inifile.Close()
inifile.DeleteIdent(section, ident)
}
而 Delphi 的 RTL 里提供有非常多的方便、实用、简洁的函数如 IntToStr、FileExists、IncludeTrailingBackslash 等等等等,我也打算慢慢地移植一些到 Golang,算是造点基础的轮子吧。
// Copyright 2016~2017 ecofast(无尽愿). All rights reserved.
// Use of this source code is governed by a BSD-style license. // Package sysutils implements some useful system utility functions
// in the way of which Delphi(2007) RTL has done.
package sysutils import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
) func CheckError(e error) {
if e != nil {
panic(e)
}
} func BoolToStr(b bool) string {
if b {
return "1"
}
return "0"
} func StrToBool(s string) bool {
if ret, err := strconv.ParseBool(s); err == nil {
return ret
}
return false
} func FloatToStr(f float64) string {
return fmt.Sprintf("%g", f)
} func GetApplicationPath() string {
path := filepath.Dir(os.Args[0])
return path + string(os.PathSeparator)
} func DirectoryExists(path string) bool {
fileInfo, err := os.Stat(path)
if err == nil && fileInfo.IsDir() {
return true
}
return false
} func FileExists(filename string) bool {
_, err := os.Stat(filename)
return err == nil || os.IsExist(err)
} func CreateFile(filename string) bool {
// os.MkdirAll(path.Dir(filename))
_, err := os.Create(filename)
if err == nil {
return true
}
return false
} func IncludeTrailingBackslash(path string) string {
if !strings.HasSuffix(path, string(os.PathSeparator)) {
return path + string(os.PathSeparator)
}
return path
}
最后再来个 litelog,基本照搬的 Go Recipes 里的代码。
// Copyright 2016~2017 ecofast(无尽愿). All rights reserved.
// Use of this source code is governed by a BSD-style license. // Package litelog provides a logging infrastructure with an option
// to set the log level, log file and write log data into log file
package litelog import (
"io"
"io/ioutil"
"log"
"os"
) // holds the log level
type LogLvl int const (
// logs nothing
LvlNone LogLvl = iota
// logs everything
LvlTrace
// logs Info, Warnings and Errors
LvlInfo
// logs Warnings and Errors
LvlWarning
// just logs Errors
LvlError
) // package level variables which are pointers to log.Logger
var (
Trace *log.Logger
Info *log.Logger
Warning *log.Logger
Error *log.Logger
) // initializes log.Logger objects
func initLogger(trace, info, warn, err io.Writer, flags int) {
flag := log.Ldate | log.Ltime | log.Lshortfile
if flags != 0 {
flag = flags
}
Trace = log.New(trace, "[Trace] ", flag)
Info = log.New(info, "[Info] ", flag)
Warning = log.New(warn, "[Warning] ", flag)
Error = log.New(err, "[Error] ", flag)
} // Setup logging facilities
func Initialize(loglvl LogLvl, logflag int, logfile string) {
logFile, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("Error opening log file: %s", err.Error())
} switch loglvl {
case LvlTrace:
initLogger(logFile, logFile, logFile, logFile, logflag)
return
case LvlInfo:
initLogger(ioutil.Discard, logFile, logFile, logFile, logflag)
return
case LvlWarning:
initLogger(ioutil.Discard, ioutil.Discard, logFile, logFile, logflag)
return
case LvlError:
initLogger(ioutil.Discard, ioutil.Discard, ioutil.Discard, logFile, logflag)
return
default:
initLogger(ioutil.Discard, ioutil.Discard, ioutil.Discard, ioutil.Discard, logflag)
logFile.Close()
return
}
}
这是示例代码和执行结果。
// litelogdemo project main.go
package main import (
"errors"
"flag"
"litelog" "github.com/ecofast/sysutils"
) func main() {
loglvl := flag.Int("loglvl", 0, "an integer value(0--4)")
flag.Parse()
litelog.Initialize(litelog.LogLvl(*loglvl), 0, sysutils.GetApplicationPath()+"logs.txt")
litelog.Trace.Println("=====Main started=====")
test()
err := errors.New("Sample error")
litelog.Error.Println(err.Error())
litelog.Trace.Println("=====Main completed=====")
} func test() {
litelog.Trace.Println("Test started")
for i := 0; i < 10; i++ {
litelog.Info.Println("Counter value is:", i)
}
litelog.Warning.Println("The counter variable is not being used")
litelog.Trace.Println("Test completed")
}
iniutils for Golang的更多相关文章
- Golang, 以17个简短代码片段,切底弄懂 channel 基础
(原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的IM服务器,所以复习了下之前一直没怎么使用的协程.管道等高并发编程知识 ...
- 说说Golang的使用心得
13年上半年接触了Golang,对Golang十分喜爱.现在是2015年,离春节还有几天,从开始学习到现在的一年半时间里,前前后后也用Golang写了些代码,其中包括业余时间的,也有产品项目中的.一直 ...
- TODO:Golang指针使用注意事项
TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...
- Golang 编写的图片压缩程序,质量、尺寸压缩,批量、单张压缩
目录: 前序 效果图 简介 全部代码 前序: 接触 golang 不久,一直是边学边做,边总结,深深感到这门语言的魅力,等下要跟大家分享是最近项目 服务端 用到的图片压缩程序,我单独分离了出来,做成了 ...
- golang struct扩展函数参数命名警告
今天在使用VSCode编写golang代码时,定义一个struct,扩展几个方法,如下: package storage import ( "fmt" "github.c ...
- golang语言构造函数
1.构造函数定义 构造函数 ,是一种特殊的方法.主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数 ,可根据其参数个 ...
- TODO:Golang语言TCP/UDP协议重用地址端口
TODO:Golang语言TCP/UDP协议重用地址端口 这是一个简单的包来解决重用地址的问题. go net包(据我所知)不允许设置套接字选项. 这在尝试进行TCP NAT时尤其成问题,其需要在同一 ...
- golang的安装
整理了一下,网上关于golang的安装有三种方式(注明一下,我的环境为CentOS-6.x, 64bit) 方式一:yum安装(最简单) rpm -Uvh http://dl.fedoraprojec ...
- golang枚举类型 - iota用法拾遗
在c#.java等高级语言中,经常会用到枚举类型来表示状态等.在golang中并没有枚举类型,如何实现枚举呢?首先从枚举的概念入手. 1.枚举类型定义 从百度百科查询解释如下:http://baike ...
随机推荐
- angularjs 动态加载事件的另一种实现
/** 初始化酒店列表 */ function inintHotel(params,url,$http,$scope){ $http.jsonp(url).success(function(res, ...
- 关于checkbox的一些问题(全选,反选,以及取值)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 《阿Q正传》读后感
kindle大法好. 利用坐车的时间阅读完了鲁迅先生写的<阿Q正传>, 心中感慨良多, 记下等以后翻看这些摸不着的回忆吧. 我没看过实体书版, 电子书版的<阿Q正传>注解很详细 ...
- 6. support vector machine
1. 了解SVM 1. Logistic regression 与SVM超平面 给定一些数据点,它们分别属于两个不同的类,现在要找到一个线性分类器把这些数据分成两类.如果用x表示数据点,用y表示类别( ...
- Centos minimal安装
Q:为什么要安装minimal版本?而不是完整版 A:因为它资源小啊 @ @ 怎么安装就不说了,网上资源大把,Centos7好像变化挺大,mysql都装不上,还是装6吧~ 1.安装完是不能联网的,解决 ...
- JUnit操作指南-批量执行单元测试(将多个测试类捆绑在一起执行)
相关链接:https://github.com/junit-team/junit4/wiki/Aggregating-tests-in-suites
- ubuntu14.04下安装python3.4.2
1. python安装包的下载地址:https://www.python.org/downloads/ 我的python安装包下载地址:https://www.python.org/ftp/pytho ...
- 。。。欢乐捕鱼App WeX5 连接打包代理服务失败,请检查代理服务地址是否正确。。。
今天学习了WeX5,第一次使用,使用它打包一个Web App 欢乐捕鱼的时候,在最终打包生成Native App的时候突然报错了,说:"连接打包代理服务失败,请检查代理服务地址是否正确&qu ...
- Json_异常_net.sf.json.JSONException: JSONObject["solution"] not found.
net.sf.json.JSONException: JSONObject["solution"] not found. 没有这个元素造成的. 问题代码: JSONObject j ...
- paper 116:自然图像抠图/视频抠像技术梳理(image matting, video matting)
1. Bayesian Matting, Chuang, CVPR 2001.http://grail.cs.washington.edu/projects/digital-matting/paper ...