From f56cb902823885138a39207db545d3a70c1c54bd Mon Sep 17 00:00:00 2001 From: sirliu Date: Sun, 31 Dec 2023 00:01:03 +0800 Subject: [PATCH 1/2] WriteCsvFile now support custom delimiter,Add write map slice to csv --- fileutil/file.go | 63 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/fileutil/file.go b/fileutil/file.go index 0cd45314..6e74f3f3 100644 --- a/fileutil/file.go +++ b/fileutil/file.go @@ -571,8 +571,10 @@ func ReadCsvFile(filepath string) ([][]string, error) { } // WriteCsvFile write content to target csv file. +// append: append to existing csv file +// delimiter: specifies csv delimiter // Play: https://go.dev/play/p/dAXm58Q5U1o -func WriteCsvFile(filepath string, records [][]string, append bool) error { +func WriteCsvFile(filepath string, records [][]string, append bool, delimiter ...rune) error { flag := os.O_RDWR | os.O_CREATE if append { @@ -587,7 +589,19 @@ func WriteCsvFile(filepath string, records [][]string, append bool) error { defer f.Close() writer := csv.NewWriter(f) - writer.Comma = ',' + // 设置默认分隔符为逗号,除非另外指定 + if len(delimiter) > 0 { + writer.Comma = delimiter[0] + } else { + writer.Comma = ',' + } + + // 遍历所有记录并处理包含分隔符或双引号的单元格 + for i := range records { + for j := range records[i] { + records[i][j] = escapeCSVField(records[i][j], writer.Comma) + } + } return writer.WriteAll(records) } @@ -646,3 +660,48 @@ func ReadFile(path string) (reader io.ReadCloser, closeFn func(), err error) { return nil, func() {}, errors.New("unknown file type") } } + +// escapeCSVField 处理单元格内容,如果包含分隔符,则用双引号包裹 +func escapeCSVField(field string, delimiter rune) string { + // 替换所有的双引号为两个双引号 + escapedField := strings.ReplaceAll(field, "\"", "\"\"") + + // 如果字段包含分隔符、双引号或换行符,用双引号包裹整个字段 + if strings.ContainsAny(escapedField, string(delimiter)+"\"\n") { + escapedField = fmt.Sprintf("\"%s\"", escapedField) + } + + return escapedField +} + +// map切片写入csv文件中 +func WriteMapsToCSV(filepath string, records []map[string]string, append_to_existing_file bool, delimiter ...rune) error { + var datas_to_write [][]string + // 标题(列名) + var headers []string + if len(records) > 0 { + for key := range records[0] { + headers = append(headers, key) + } + } + // 追加模式不重复写字段名 + if !append_to_existing_file { + datas_to_write = append(datas_to_write, headers) + } + // 写入数据行 + for _, record := range records { + var row []string + for _, header := range headers { + row = append(row, record[header]) + } + datas_to_write = append(datas_to_write, row) + } + // 提取自定义分隔符 + var sep rune + if len(delimiter) > 0 { + sep = delimiter[0] + } else { + sep = ',' + } + return WriteCsvFile(filepath, datas_to_write, append_to_existing_file, sep) +} From e6ca030e1ca718dd2c0e775a3d684660f94edb4b Mon Sep 17 00:00:00 2001 From: colorcrow Date: Sun, 31 Dec 2023 21:43:36 +0800 Subject: [PATCH 2/2] add trace func time --- datetime/datetime.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/datetime/datetime.go b/datetime/datetime.go index db806494..5432debd 100644 --- a/datetime/datetime.go +++ b/datetime/datetime.go @@ -381,3 +381,12 @@ func TimestampNano(timezone ...string) int64 { return t.UnixNano() } + +// TraceFuncTime: trace the func costed time,just call it at top of the func like `defer TraceFuncTime()()` +func TraceFuncTime() func() { + pre := time.Now() + return func() { + elapsed := time.Since(pre) + fmt.Println("Costs Time:\t", elapsed) + } +}