github.com/suiyunonghen/DxCommonLib@v0.5.3/StringList.go (about)

     1  /*
     2  仿Delphi的通用类库
     3  GStringList类似于TStringList
     4  Autor: 不得闲
     5  QQ:75492895
     6  */
     7  package DxCommonLib
     8  
     9  import (
    10  	"fmt"
    11  	"os"
    12  	"strings"
    13  	"io"
    14  	"bytes"
    15  	"bufio"
    16  )
    17  
    18  type (
    19  	IStrings interface {
    20  		Count() int
    21  		Strings(index int) string
    22  		SetStrings(index int, str string)
    23  		Text() string
    24  		SetText(text string)
    25  		LoadFromFile(fileName string)
    26  		SaveToFile(fileName string)
    27  		Add(str string)
    28  		Insert(Index int, str string)
    29  		Delete(index int)
    30  		AddStrings(strs IStrings)
    31  		AddSlice(strs []string)
    32  		Clear()
    33  		IndexOf(str string) int
    34  
    35  		AddPair(Name, Value string)
    36  		IndexOfName(Name string) int
    37  		ValueFromIndex(index int) string
    38  		ValueByName(Name string) string
    39  		Names(Index int) string
    40  		AsSlice() []string
    41  	}
    42  
    43  	LineBreakMode byte
    44  
    45  	GStringList struct {
    46  		strings           []string
    47  		LineBreak         LineBreakMode
    48  		UnknownCodeUseGbk bool //未知编码的时候采用GBK编码打开
    49  	}
    50  )
    51  
    52  const (
    53  	LBK_CRLF LineBreakMode = iota
    54  	LBK_CR
    55  	LBK_LF
    56  )
    57  
    58  func (lst *GStringList) LineBreakStr() string {
    59  	switch lst.LineBreak {
    60  	case LBK_CRLF:
    61  		return "\r\n"
    62  	case LBK_CR:
    63  		return "\r"
    64  	case LBK_LF:
    65  		return "\n"
    66  	default:
    67  		return "\r\n"
    68  	}
    69  }
    70  
    71  func (lst *GStringList) Count() int {
    72  	if lst.strings == nil {
    73  		return 0
    74  	}
    75  	return len(lst.strings)
    76  }
    77  
    78  func (lst *GStringList) Strings(index int) string {
    79  	if index >= 0 && index < len(lst.strings) {
    80  		return lst.strings[index]
    81  	}
    82  	return ""
    83  }
    84  
    85  func (lst *GStringList) SetStrings(index int, str string) {
    86  	if lst.strings == nil {
    87  		lst.strings = make([]string, 0, 64)
    88  	}
    89  	if index >= 0 && index < len(lst.strings) {
    90  		lst.strings[index] = str
    91  	}
    92  }
    93  
    94  func (lst *GStringList) Text() string {
    95  	if lst.Count() == 0 {
    96  		return ""
    97  	}
    98  	buffer := bytes.NewBuffer(make([]byte,0,1024))
    99  	count := lst.Count()
   100  	for i := 0;i<count;i++{
   101  		buffer.WriteString(lst.strings[i])
   102  		if i < count - 1{
   103  			buffer.WriteString(lst.LineBreakStr())
   104  		}
   105  	}
   106  	return FastByte2String(buffer.Bytes())
   107  }
   108  
   109  func (lst *GStringList) SetText(text string) {
   110  	lst.strings = strings.Split(text, lst.LineBreakStr())
   111  }
   112  
   113  func (lst *GStringList) LoadFromFile(fileName string) {
   114  	if finfo, err := os.Stat(fileName); err == nil && !finfo.IsDir() {
   115  		if file, err := os.Open(fileName); err == nil {
   116  			//先判定文件格式,是否为utf8或者utf16,去掉BOM
   117  			if lst.strings == nil{
   118  				lst.strings = make([]string,0,100)
   119  			}else{
   120  				lst.strings = lst.strings[:0]
   121  			}
   122  			defer file.Close()
   123  			var bt [3]byte
   124  			filecodeType := File_Code_Unknown
   125  			if _,err := file.Read(bt[:3]);err==nil{
   126  				if bt[0] == 0xFF && bt[1] == 0xFE { //UTF-16(Little Endian)
   127  					file.Seek(-1,io.SeekCurrent)
   128  					filecodeType = File_Code_Utf16LE
   129  				}else if bt[0] == 0xFE && bt[1] == 0xFF{ //UTF-16(big Endian)
   130  					file.Seek(-1,io.SeekCurrent)
   131  					filecodeType = File_Code_Utf16BE
   132  				}else if bt[0] == 0xEF && bt[1] == 0xBB && bt[2] == 0xBF { //UTF-8
   133  					filecodeType = File_Code_Utf8
   134  				}else{
   135  					file.Seek(-3,io.SeekCurrent)
   136  				}
   137  			}
   138  			reader := bufio.NewReader(file)
   139  			for{
   140  				line,err := reader.ReadBytes('\n')
   141  				if filecodeType == File_Code_Utf16LE{ //小端结尾多一个空白的0标记
   142  					reader.ReadByte()
   143  				}
   144  				if err == nil || err == io.EOF{
   145  					linelen := len(line)
   146  					if linelen >= 2{
   147  						if line[linelen-2] == '\r'{
   148  							line = line[:linelen - 2]
   149  						}else if line[linelen - 1] == '\n'{
   150  							line = line[:linelen-1]
   151  						}
   152  					}
   153  					if linelen>0{
   154  						switch filecodeType {
   155  						case File_Code_Utf8:
   156  							lst.Add(FastByte2String(line))
   157  						case File_Code_Utf16LE,File_Code_Utf16BE:
   158  							lst.Add(UTF16Byte2string(line,filecodeType == File_Code_Utf16BE))
   159  						case File_Code_GBK,File_Code_Unknown:
   160  							if tmpbytes, err := GBK2Utf8(line); err == nil {
   161  								lst.Add(FastByte2String(tmpbytes))
   162  							}else{
   163  								lst.Add(FastByte2String(line))
   164  							}
   165  						}
   166  					}else{
   167  						lst.Add("")
   168  					}
   169  					if err != nil{
   170  						return
   171  					}
   172  				}else{
   173  					return
   174  				}
   175  			}
   176  		}
   177  	}
   178  }
   179  
   180  func (lst *GStringList)LoadFromReader(r io.Reader,filecodeType FileCodeMode)  {
   181  	lst.Clear()
   182  	reader := bufio.NewReader(r)
   183  	for{
   184  		line,err := reader.ReadBytes('\n')
   185  		if filecodeType == File_Code_Utf16LE{ //小端结尾多一个空白的0标记
   186  			reader.ReadByte()
   187  		}
   188  		if err == nil || err == io.EOF{
   189  			linelen := len(line)
   190  			if linelen >= 2{
   191  				if line[linelen-2] == '\r'{
   192  					line = line[:linelen - 2]
   193  				}else if line[linelen - 1] == '\n'{
   194  					line = line[:linelen-1]
   195  				}
   196  			}
   197  			if linelen>0{
   198  				switch filecodeType {
   199  				case File_Code_Utf8:
   200  					lst.Add(FastByte2String(line))
   201  				case File_Code_Utf16LE,File_Code_Utf16BE:
   202  					lst.Add(UTF16Byte2string(line,filecodeType == File_Code_Utf16BE))
   203  				case File_Code_GBK,File_Code_Unknown:
   204  					if tmpbytes, err := GBK2Utf8(line); err == nil {
   205  						lst.Add(FastByte2String(tmpbytes))
   206  					}else{
   207  						lst.Add(FastByte2String(line))
   208  					}
   209  				}
   210  			}else{
   211  				lst.Add("")
   212  			}
   213  			if err != nil{
   214  				return
   215  			}
   216  		}else{
   217  			return
   218  		}
   219  	}
   220  }
   221  
   222  func (lst *GStringList) SaveToFile(fileName string) {
   223  	//文件要先写入UTF8的BOM
   224  	if file, err := os.OpenFile(fileName, os.O_CREATE|os.O_TRUNC, 0644); err == nil {
   225  		count := lst.Count()
   226  		if count > 0 {
   227  			file.Write([]byte{0xEF, 0xBB, 0xBF})
   228  			//写入内容
   229  			buffer := bytes.NewBuffer(make([]byte,0,1024))
   230  			for i := 0;i<count;i++{
   231  				buffer.WriteString(lst.strings[i])
   232  				if i < count - 1{
   233  					buffer.WriteString(lst.LineBreakStr())
   234  				}
   235  			}
   236  			file.Write(buffer.Bytes())
   237  		}
   238  		file.Close()
   239  	}
   240  }
   241  
   242  func (lst *GStringList) Add(str string) {
   243  	if lst.strings == nil {
   244  		lst.strings = make([]string, 0, 64)
   245  	}
   246  	lst.strings = append(lst.strings, str)
   247  }
   248  
   249  func (lst *GStringList) Insert(Index int, str string) {
   250  	if lst.strings == nil {
   251  		lst.strings = make([]string, 0, 64)
   252  	}
   253  	if Index >= 0 && Index < len(lst.strings) {
   254  		temp := append([]string{}, lst.strings[Index:]...)
   255  		lst.strings = append(lst.strings[0:Index], str)
   256  		lst.strings = append(lst.strings, temp...)
   257  	} else {
   258  		lst.Add(str)
   259  	}
   260  }
   261  func (lst *GStringList) Delete(index int) {
   262  	if lst.Count() > 0 && index >= 0 && index < len(lst.strings) {
   263  		lst.strings = append(lst.strings[0:index], lst.strings[index+1:]...)
   264  	}
   265  }
   266  
   267  func (lst *GStringList) AddStrings(strs IStrings) {
   268  	for idx := 0; idx < strs.Count(); idx++ {
   269  		lst.Add(strs.Strings(idx))
   270  	}
   271  }
   272  
   273  func (lst *GStringList) AddSlice(strs []string) {
   274  	if lst.strings != nil {
   275  		lst.strings = append(lst.strings, strs...)
   276  	} else {
   277  		lst.strings = strs
   278  	}
   279  }
   280  func (lst *GStringList) Clear() {
   281  	if lst.strings != nil {
   282  		lst.strings = lst.strings[:0]
   283  	}
   284  }
   285  func (lst *GStringList) IndexOf(str string) int {
   286  	if lst.Count() > 0 {
   287  		for idx, v := range lst.strings {
   288  			if v == str {
   289  				return idx
   290  			}
   291  		}
   292  	}
   293  	return -1
   294  }
   295  
   296  func (lst *GStringList) AddPair(Name, Value string) {
   297  	lst.strings = append(lst.strings, fmt.Sprintf("%s=%s", Name, Value))
   298  }
   299  func (lst *GStringList) IndexOfName(Name string) int {
   300  	if lst.Count() > 0 {
   301  		for idx, v := range lst.strings {
   302  			if eidx := strings.IndexByte(v, '='); eidx > 0 {
   303  				bt := []byte(v)
   304  				if string(bt[:eidx]) == Name {
   305  					return idx
   306  				}
   307  			}
   308  		}
   309  	}
   310  	return -1
   311  }
   312  
   313  func (lst *GStringList) ValueFromIndex(index int) string {
   314  	if lst.Count() == 0 {
   315  		return ""
   316  	}
   317  	if index >= 0 && index < len(lst.strings) {
   318  		str := lst.strings[index]
   319  		if idx := strings.IndexByte(str, '='); idx > 0 {
   320  			bt := []byte(str)
   321  			return FastByte2String(bt[idx+1:])
   322  		}
   323  		return ""
   324  	}
   325  	return ""
   326  }
   327  
   328  func (lst *GStringList) ValueByName(Name string) string {
   329  	if lst.Count() > 0 {
   330  		for _, v := range lst.strings {
   331  			if eidx := strings.IndexByte(v, '='); eidx > 0 {
   332  				bt := []byte(v)
   333  				if string(bt[:eidx]) == Name {
   334  					return FastByte2String(bt[eidx+1:])
   335  				}
   336  			}
   337  		}
   338  	}
   339  	return ""
   340  }
   341  func (lst *GStringList) Names(Index int) string {
   342  	if lst.Count() == 0 {
   343  		return ""
   344  	}
   345  	if Index >= 0 && Index < len(lst.strings) {
   346  		str := lst.strings[Index]
   347  		if idx := strings.IndexByte(str, '='); idx > 0 {
   348  			bt := []byte(str)
   349  			return FastByte2String(bt[:idx])
   350  		}
   351  		return ""
   352  	}
   353  	return ""
   354  }
   355  func (lst *GStringList) AsSlice() []string {
   356  	return lst.strings
   357  }