1 Star 0 Fork 0

go / gopkg

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
csv.go 4.06 KB
一键复制 编辑 原始数据 按行查看 历史
dilong.liao 提交于 2023-04-18 12:02 . 更新域名
package csv
import (
"encoding/csv"
"errors"
"gitee.com/lllgo/gopkg/log"
"os"
)
// csv操作封装 为了便于操作 数据采用map存储
type Table struct {
//文件路径
FileName string
//数据开始行,值从0开始 默认1 第一行一般为列名
StartRow int
//数据对象转换为csv字符串数组
recordToCsv RecordToCsvFunc
//csv字符串数组转换为数据对象
csvSliceToRecord CsvSliceToRecordFunc
Comma, Comment rune
UseCRLF bool
file *os.File
//存储数据记录
dataRecords []Record
cacheMeta []Meta
notDataRecords [][]string
needRead bool
}
type Meta struct {
Id int
}
type Record interface{}
type RecordToCsvFunc func(r Record, m Meta) []string
type CsvSliceToRecordFunc func(v []string, m Meta) Record
func NewTable(filename string, f1 RecordToCsvFunc, f2 CsvSliceToRecordFunc) *Table {
flag := os.O_RDWR | os.O_CREATE | os.O_SYNC
file, err := os.OpenFile(filename, flag, 0666)
if err != nil {
log.Error(err)
return nil
}
return &Table{
FileName: filename,
StartRow: 1,
file: file,
Comma: ',',
recordToCsv: f1,
csvSliceToRecord: f2,
cacheMeta: make([]Meta, 0),
needRead: true,
}
}
// 读取所有数据
func (t *Table) Read() error {
if !t.needRead {
return nil
}
reader := csv.NewReader(t.file)
if reader == nil {
return errors.New("NewReader return nil, file:" + t.FileName)
}
reader.Comma = t.Comma
reader.Comment = t.Comment
records, err := reader.ReadAll()
if err != nil {
return err
}
if len(records) < t.StartRow {
return errors.New(t.FileName + " is empty")
}
var allRecords []Record
for i := t.StartRow; i < len(records); i++ {
meta := Meta{Id: i - t.StartRow + 1}
r := t.csvSliceToRecord(records[i], meta)
allRecords = append(allRecords, r)
t.cacheMeta = append(t.cacheMeta, meta)
}
t.dataRecords = allRecords
t.notDataRecords = records[0:t.StartRow]
t.needRead = false
return nil
}
// 按条件查找记录
func (t *Table) GetRecords(cond ...func(r Record, m Meta) bool) []Record {
rs, _ := t.GetRecordsAndMeta(cond...)
return rs
}
// 按条件查找记录
func (t *Table) GetRecordsAndMeta(cond ...func(r Record, m Meta) bool) (rs []Record, ms []Meta) {
if len(cond) == 0 {
return t.dataRecords, t.cacheMeta
}
lc := len(cond) - 1
for i, r := range t.dataRecords {
for j, c := range cond {
if !c(r, t.cacheMeta[i]) {
continue
}
if lc == j {
rs = append(rs, r)
ms = append(ms, t.cacheMeta[i])
}
}
}
return
}
// 按条件更新记录
func (t *Table) SetRecordByCond(new Record, cond ...func(r Record, m Meta) bool) error {
lc := len(cond) - 1
for i, r := range t.dataRecords {
for j, c := range cond {
if !c(r, t.cacheMeta[i]) {
continue
}
if lc == j {
t.dataRecords[i] = new
}
}
}
return t.WriteAll()
}
// 按ID更新记录
func (t *Table) SetRecordById(new Record, id int) error {
t.dataRecords[getIndexById(id)] = new
return t.WriteAll()
}
// 按ID更新记录
func (t *Table) RemoveRecordById(id int) error {
t.dataRecords = t.dataRecords[0:getIndexById(id)]
t.dataRecords = append(t.dataRecords, t.dataRecords[id:])
return t.WriteAll()
}
// 重置所有数据
func (t *Table) WriteAll() error {
//清空旧文件
if err := t.file.Truncate(0); err != nil {
return err
}
if _, err := t.file.Seek(0, 0); err != nil {
return err
}
csvRecords := t.notDataRecords
for i, record := range t.dataRecords {
csvRecords = append(csvRecords, t.recordToCsv(record, t.cacheMeta[i]))
}
return t.getWriter().WriteAll(csvRecords)
}
func (t *Table) getWriter() *csv.Writer {
writer := csv.NewWriter(t.file)
writer.Comma = t.Comma
writer.UseCRLF = t.UseCRLF
return writer
}
// 添加记录
func (t *Table) Insert(record Record) error {
t.dataRecords = append(t.dataRecords, record)
meta := Meta{Id: len(t.dataRecords)}
t.cacheMeta = append(t.cacheMeta, meta)
writer := t.getWriter()
if err := writer.Write(t.recordToCsv(record, meta)); err != nil {
return err
}
writer.Flush()
return nil
}
func getIndexById(id int) int {
return id - 1
}
Go
1
https://gitee.com/lllgo/gopkg.git
git@gitee.com:lllgo/gopkg.git
lllgo
gopkg
gopkg
v0.1.2

搜索帮助