github.com/team-ide/go-dialect@v1.9.20/worker/data_source_text.go (about)

     1  package worker
     2  
     3  import (
     4  	"bufio"
     5  	"errors"
     6  	"fmt"
     7  	"github.com/team-ide/go-dialect/dialect"
     8  	"io"
     9  	"os"
    10  	"strings"
    11  )
    12  
    13  func NewDataSourceText(param *DataSourceParam) (res DataSource) {
    14  	res = &dataSourceText{
    15  		DataSourceParam: param,
    16  	}
    17  	return
    18  }
    19  
    20  type dataSourceText struct {
    21  	*DataSourceParam
    22  	saveFile      *os.File
    23  	isStop        bool
    24  	headerWritten bool
    25  }
    26  
    27  func (this_ *dataSourceText) Stop() {
    28  	this_.isStop = true
    29  }
    30  
    31  func (this_ *dataSourceText) ReadStart() (err error) {
    32  	return
    33  }
    34  func (this_ *dataSourceText) ReadEnd() (err error) {
    35  	return
    36  }
    37  func (this_ *dataSourceText) Read(columnList []*dialect.ColumnModel, onRead func(data *DataSourceData) (err error)) (err error) {
    38  	defer func() {
    39  		if e := recover(); e != nil {
    40  			err = errors.New(fmt.Sprint(e))
    41  		}
    42  	}()
    43  	if this_.Path == "" {
    44  		err = errors.New("文件地址不能为空")
    45  		return
    46  	}
    47  	f, err := os.Open(this_.Path)
    48  	if err != nil {
    49  		return
    50  	}
    51  	buf := bufio.NewReader(f)
    52  	var line string
    53  	var rowInfo string
    54  	separator := this_.GetTextSeparator()
    55  	columnLength := len(columnList)
    56  	if columnLength == 0 {
    57  		err = errors.New("column is null")
    58  		return
    59  	}
    60  	for {
    61  		if this_.isStop {
    62  			return
    63  		}
    64  		line, err = buf.ReadString('\n')
    65  		if line != "" {
    66  			if rowInfo == "" {
    67  				rowInfo = line
    68  			} else {
    69  				rowInfo += line
    70  			}
    71  
    72  			ss := strings.Split(strings.TrimSpace(rowInfo), separator)
    73  			if len(ss) > columnLength {
    74  				err = errors.New("row [" + rowInfo + "] can not to column names [" + strings.Join(GetColumnNames(columnList), ",") + "]")
    75  				return
    76  			}
    77  			if len(ss) == columnLength {
    78  				rowInfo = strings.TrimSpace(rowInfo)
    79  				if rowInfo != "" {
    80  					rowInfo = strings.ReplaceAll(rowInfo, this_.GetLinefeed(), "\n")
    81  					err = readRow(this_.Dia, rowInfo, separator, columnList, onRead)
    82  					if err != nil {
    83  						return
    84  					}
    85  				}
    86  				rowInfo = ""
    87  			}
    88  		}
    89  		if err != nil {
    90  			if err == io.EOF { //读取结束,会报EOF
    91  				err = nil
    92  			}
    93  			break
    94  		}
    95  	}
    96  	if err != nil {
    97  		return
    98  	}
    99  	rowInfo = strings.TrimSpace(rowInfo)
   100  	if rowInfo != "" {
   101  		err = readRow(this_.Dia, rowInfo, separator, columnList, onRead)
   102  		if err != nil {
   103  			return
   104  		}
   105  	}
   106  	return
   107  }
   108  
   109  func GetColumnNames(columnList []*dialect.ColumnModel) (columnNames []string) {
   110  	for _, column := range columnList {
   111  		columnNames = append(columnNames, column.ColumnName)
   112  	}
   113  	return
   114  }
   115  
   116  func readRow(dia dialect.Dialect, rowInfo string, separator string, columnList []*dialect.ColumnModel, onRead func(data *DataSourceData) (err error)) (err error) {
   117  	calls := strings.Split(rowInfo, separator)
   118  	data := make(map[string]interface{})
   119  	if len(calls) != len(columnList) {
   120  		err = errors.New("row [" + rowInfo + "] can not to column names [" + strings.Join(GetColumnNames(columnList), ",") + "]")
   121  		return
   122  	}
   123  	for i, column := range columnList {
   124  		v := calls[i]
   125  		if !column.ColumnNotNull && v == "" {
   126  			continue
   127  		}
   128  		var info *dialect.ColumnTypeInfo
   129  		info, err = dia.GetColumnTypeInfo(column)
   130  		if err != nil {
   131  			return
   132  		}
   133  		if info.IsDateTime || info.IsNumber {
   134  			if v == "" {
   135  				continue
   136  			}
   137  		}
   138  
   139  		data[column.ColumnName] = v
   140  	}
   141  	err = onRead(&DataSourceData{
   142  		HasData: true,
   143  		Data:    data,
   144  	})
   145  	return
   146  }
   147  
   148  func (this_ *dataSourceText) WriteStart() (err error) {
   149  
   150  	if this_.Path == "" {
   151  		err = errors.New("文件地址不能为空")
   152  		return
   153  	}
   154  
   155  	this_.saveFile, err = os.Create(this_.Path)
   156  	if err != nil {
   157  		return
   158  	}
   159  	return
   160  }
   161  func (this_ *dataSourceText) WriteEnd() (err error) {
   162  	if this_.saveFile != nil {
   163  		err = this_.saveFile.Close()
   164  		return
   165  	}
   166  	return
   167  }
   168  
   169  func (this_ *dataSourceText) WriteHeader(columnList []*dialect.ColumnModel) (err error) {
   170  	if this_.headerWritten {
   171  		return
   172  	}
   173  	this_.headerWritten = true
   174  
   175  	if this_.saveFile == nil {
   176  		err = this_.WriteStart()
   177  		if err != nil {
   178  			return
   179  		}
   180  	}
   181  
   182  	if this_.isStop {
   183  		return
   184  	}
   185  
   186  	var valueList []string
   187  	for _, column := range columnList {
   188  		str := column.ColumnName
   189  		str = strings.ReplaceAll(str, "\r\n", this_.GetLinefeed())
   190  		str = strings.ReplaceAll(str, "\n", this_.GetLinefeed())
   191  		str = strings.ReplaceAll(str, "\r", this_.GetLinefeed())
   192  		valueList = append(valueList, str)
   193  	}
   194  
   195  	_, err = this_.saveFile.WriteString(strings.Join(valueList, this_.GetTextSeparator()) + "\n")
   196  	if err != nil {
   197  		return
   198  	}
   199  	return
   200  }
   201  
   202  func (this_ *dataSourceText) Write(data *DataSourceData) (err error) {
   203  	defer func() {
   204  		if e := recover(); e != nil {
   205  			err = errors.New(fmt.Sprint(e))
   206  		}
   207  	}()
   208  	if this_.saveFile == nil {
   209  		err = this_.WriteStart()
   210  		if err != nil {
   211  			return
   212  		}
   213  	}
   214  
   215  	if this_.isStop {
   216  		return
   217  	}
   218  	columnList := data.ColumnList
   219  	if data.Data == nil || columnList == nil {
   220  		return
   221  	}
   222  	var valueList []string
   223  	for _, column := range data.ColumnList {
   224  		str := dialect.GetStringValue(data.Data[column.ColumnName])
   225  		str = strings.ReplaceAll(str, "\r\n", this_.GetLinefeed())
   226  		str = strings.ReplaceAll(str, "\n", this_.GetLinefeed())
   227  		str = strings.ReplaceAll(str, "\r", this_.GetLinefeed())
   228  		valueList = append(valueList, str)
   229  	}
   230  
   231  	_, err = this_.saveFile.WriteString(strings.Join(valueList, this_.GetTextSeparator()) + "\n")
   232  	if err != nil {
   233  		return
   234  	}
   235  
   236  	return
   237  }
   238  
   239  func isRowEnd(rowInfo string) (isEnd bool) {
   240  
   241  	var inStringLevel int
   242  	var inStringPack byte
   243  	var thisChar byte
   244  	var lastChar byte
   245  
   246  	var stringPackChars = []byte{'"', '\''}
   247  	for i := 0; i < len(rowInfo); i++ {
   248  		thisChar = rowInfo[i]
   249  		if i > 0 {
   250  			lastChar = rowInfo[i-1]
   251  		}
   252  
   253  		// inStringLevel == 0 表示 不在 字符串 包装 中
   254  		if thisChar == ';' && inStringLevel == 0 {
   255  		} else {
   256  			packCharIndex := dialect.BytesIndex(stringPackChars, thisChar)
   257  			if packCharIndex >= 0 {
   258  				// inStringLevel == 0 表示 不在 字符串 包装 中
   259  				if inStringLevel == 0 {
   260  					inStringPack = stringPackChars[packCharIndex]
   261  					// 字符串包装层级 +1
   262  					inStringLevel++
   263  				} else {
   264  					// 如果有转义符号 类似 “\'”,“\"”
   265  					if lastChar == '\\' {
   266  					} else if lastChar == inStringPack {
   267  						// 如果 前一个字符 与字符串包装字符一致
   268  						inStringLevel--
   269  					} else {
   270  						// 字符串包装层级 -1
   271  						inStringLevel--
   272  					}
   273  				}
   274  			}
   275  		}
   276  
   277  	}
   278  	isEnd = inStringLevel == 0
   279  	return
   280  }