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 }