diff --git a/README.md b/README.md
index 951c1cc..7ddaa45 100644
--- a/README.md
+++ b/README.md
@@ -706,6 +706,8 @@ import "github.com/duke-git/lancet/v2/fileutil"
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
- **WriteCsvFile** : write content to target csv file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#WriteCsvFile)]
+- **WriteMapsToCsv** : write slice of map to csv file.
+ [[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#WriteMapsToCsv)]
[[play](https://go.dev/play/p/dAXm58Q5U1o)]
- **WriteBytesToFile** : write bytes to target file.
[[doc](https://github.com/duke-git/lancet/blob/main/docs/en/api/packages/fileutil.md#WriteBytesToFile)]
diff --git a/README_zh-CN.md b/README_zh-CN.md
index 97fe71e..51c574e 100644
--- a/README_zh-CN.md
+++ b/README_zh-CN.md
@@ -705,8 +705,10 @@ import "github.com/duke-git/lancet/v2/fileutil"
- **ReadCsvFile** : 读取 csv 文件内容到切片。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#ReadCsvFile)]
[[play](https://go.dev/play/p/OExTkhGEd3_u)]
-- **WriteCsvFile** : 向 csv 文件写入内容。
+- **WriteCsvFile** : 向csv文件写入切片数据。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#WriteCsvFile)]
+- **WriteMapsToCsv** : 将map切片写入csv文件中。
+ [[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#WriteMapsToCsv)]
[[play](https://go.dev/play/p/dAXm58Q5U1o)]
- **WriteBytesToFile** : 将 bytes 写入文件。
[[doc](https://github.com/duke-git/lancet/blob/main/docs/api/packages/fileutil.md#WriteBytesToFile)]
diff --git a/docs/api/packages/fileutil.md b/docs/api/packages/fileutil.md
index a5183d4..70e2499 100644
--- a/docs/api/packages/fileutil.md
+++ b/docs/api/packages/fileutil.md
@@ -45,6 +45,7 @@ import (
- [Sha](#Sha)
- [ReadCsvFile](#ReadCsvFile)
- [WriteCsvFile](#WriteCsvFile)
+- [WriteMapsToCsv](#WriteMapsToCsv)
- [WriteStringToFile](#WriteStringToFile)
- [WriteBytesToFile](#WriteBytesToFile)
- [ReadFile](#ReadFile)
@@ -754,7 +755,8 @@ func main() {
// records: 写入文件的map切片。map值必须为基本类型。会以map键的字母顺序写入。
// appendToExistingFile: 是否为追加写模式。
// delimiter: CSV文件分割符。
-func WriteMapsToCsv(filepath string, records []map[string]string, append_to_existing_file bool, delimiter ...rune) error
+// headers: CSV文件表头顺序(需要与map key保持一致),不指定时按字母排序。
+func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingFile bool, delimiter rune, headers ...[]string) error
```
示例:
@@ -779,7 +781,8 @@ func main() {
{"Name": "Jim", "Age": "21", "Gender": "male"},
}
- err := fileutil.WriteMapsToCsv(csvFilePath, records, false, ';')
+ headers := []string{"Name", "Age", "Gender"}
+ err := WriteMapsToCsv(csvFilePath, records, false, ';', headers)
if err != nil {
log.Fatal(err)
@@ -790,7 +793,7 @@ func main() {
fmt.Println(content)
// Output:
- // [[Age Gender Name] [22 female Lili] [21 male Jim]]
+ // [[Name Age Gender] [Lili 22 female] [Jim 21 male]]
}
```
diff --git a/docs/en/api/packages/fileutil.md b/docs/en/api/packages/fileutil.md
index a46be12..593062e 100644
--- a/docs/en/api/packages/fileutil.md
+++ b/docs/en/api/packages/fileutil.md
@@ -45,6 +45,7 @@ import (
- [Sha](#Sha)
- [ReadCsvFile](#ReadCsvFile)
- [WriteCsvFile](#WriteCsvFile)
+- [WriteCsvFile](#WriteCsvFile)
- [WriteMapsToCsv](#WriteMapsToCsv)
- [WriteStringToFile](#WriteStringToFile)
- [WriteBytesToFile](#WriteBytesToFile)
@@ -755,7 +756,8 @@ func main() {
// records: slice of maps to be written. the value of map should be basic type. The maps will be sorted by key in alphabeta order, then be written into csv file.
// appendToExistingFile: If true, data will be appended to the file if it exists.
// delimiter: Delimiter to use in the CSV file.
-func WriteMapsToCsv(filepath string, records []map[string]string, append_to_existing_file bool, delimiter ...rune) error
+// headers: order of the csv column headers, needs to be consistent with the key of the map.
+func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingFile bool, delimiter rune, headers ...[]string) error
```
Example:
@@ -780,7 +782,8 @@ func main() {
{"Name": "Jim", "Age": "21", "Gender": "male"},
}
- err := fileutil.WriteMapsToCsv(csvFilePath, records, false, ';')
+ headers := []string{"Name", "Age", "Gender"}
+ err := fileutil.WriteMapsToCsv(csvFilePath, records, false, ';', headers)
if err != nil {
log.Fatal(err)
@@ -791,7 +794,7 @@ func main() {
fmt.Println(content)
// Output:
- // [[Age Gender Name] [22 female Lili] [21 male Jim]]
+ // [[Name Age Gender] [Lili 22 female] [Jim 21 male]]
}
```
diff --git a/fileutil/file.go b/fileutil/file.go
index a29a2a2..e8405ec 100644
--- a/fileutil/file.go
+++ b/fileutil/file.go
@@ -760,7 +760,9 @@ func escapeCSVField(field string, delimiter rune) string {
// the maps will be sorted by key in alphabeta order, then be written into csv file.
// appendToExistingFile: If true, data will be appended to the file if it exists.
// delimiter: Delimiter to use in the CSV file.
-func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingFile bool, delimiter ...rune) error {
+// headers: order of the csv column headers, needs to be consistent with the key of the map.
+func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingFile bool, delimiter rune,
+ headers ...[]string) error {
for _, record := range records {
for _, value := range record {
if !isCsvSupportedType(value) {
@@ -769,40 +771,31 @@ func WriteMapsToCsv(filepath string, records []map[string]any, appendToExistingF
}
}
- var datasToWrite [][]string
-
- // 标题(列名)
- var headers []string
- if len(records) > 0 {
+ var columnHeaders []string
+ if len(headers) > 0 {
+ columnHeaders = headers[0]
+ } else {
for key := range records[0] {
- headers = append(headers, key)
+ columnHeaders = append(columnHeaders, key)
}
+ // sort keys in alphabeta order
+ sort.Strings(columnHeaders)
}
- // sort keys in alphabeta order
- sort.Strings(headers)
-
- // 追加模式不重复写字段名
+ var datasToWrite [][]string
if !appendToExistingFile {
- datasToWrite = append(datasToWrite, headers)
+ datasToWrite = append(datasToWrite, columnHeaders)
}
for _, record := range records {
var row []string
- for _, header := range headers {
- row = append(row, fmt.Sprintf("%v", record[header]))
+ for _, h := range columnHeaders {
+ row = append(row, fmt.Sprintf("%v", record[h]))
}
datasToWrite = append(datasToWrite, row)
}
- var sep rune
- if len(delimiter) > 0 {
- sep = delimiter[0]
- } else {
- sep = ','
- }
-
- return WriteCsvFile(filepath, datasToWrite, appendToExistingFile, sep)
+ return WriteCsvFile(filepath, datasToWrite, appendToExistingFile, delimiter)
}
// check if the value of map which to be written into csv is basic type.
@@ -814,8 +807,3 @@ func isCsvSupportedType(v interface{}) bool {
return false
}
}
-
-// sort map by key in alphabeta order.
-// func sortMap(records []map[string]any) []map[string]any {
-
-// }
diff --git a/fileutil/file_example_test.go b/fileutil/file_example_test.go
index 1932831..9fad0dc 100644
--- a/fileutil/file_example_test.go
+++ b/fileutil/file_example_test.go
@@ -339,7 +339,8 @@ func ExampleWriteMapsToCsv() {
{"Name": "Jim", "Age": "21", "Gender": "male"},
}
- err := WriteMapsToCsv(csvFilePath, records, false, ';')
+ headers := []string{"Name", "Age", "Gender"}
+ err := WriteMapsToCsv(csvFilePath, records, false, ';', headers)
if err != nil {
log.Fatal(err)
@@ -350,7 +351,7 @@ func ExampleWriteMapsToCsv() {
fmt.Println(content)
// Output:
- // [[Age Gender Name] [22 female Lili] [21 male Jim]]
+ // [[Name Age Gender] [Lili 22 female] [Jim 21 male]]
}
func ExampleWriteStringToFile() {
diff --git a/fileutil/file_test.go b/fileutil/file_test.go
index 5750670..1c0151b 100644
--- a/fileutil/file_test.go
+++ b/fileutil/file_test.go
@@ -397,7 +397,8 @@ func TestWriteMapsToCsv(t *testing.T) {
{"Name": "Jim", "Age": "21", "Gender": "male"},
}
- err := WriteMapsToCsv(csvFilePath, records, false, ';')
+ headers := []string{"Name", "Age", "Gender"}
+ err := WriteMapsToCsv(csvFilePath, records, false, ';', headers)
assert.IsNil(err)
@@ -407,9 +408,9 @@ func TestWriteMapsToCsv(t *testing.T) {
assert.Equal(3, len(content))
assert.Equal(3, len(content[0]))
- assert.Equal("22", content[1][0])
- assert.Equal("female", content[1][1])
- assert.Equal("Lili", content[1][2])
+ assert.Equal("Lili", content[1][0])
+ assert.Equal("22", content[1][1])
+ assert.Equal("female", content[1][2])
}
func TestWriteStringToFile(t *testing.T) {
diff --git a/fileutil/testdata/test3.csv b/fileutil/testdata/test3.csv
index aab46b6..d5e2f12 100644
--- a/fileutil/testdata/test3.csv
+++ b/fileutil/testdata/test3.csv
@@ -1,3 +1,3 @@
-Age;Gender;Name
-22;female;Lili
-21;male;Jim
+Name;Age;Gender
+Lili;22;female
+Jim;21;male
diff --git a/fileutil/testdata/test4.csv b/fileutil/testdata/test4.csv
index aab46b6..d5e2f12 100644
--- a/fileutil/testdata/test4.csv
+++ b/fileutil/testdata/test4.csv
@@ -1,3 +1,3 @@
-Age;Gender;Name
-22;female;Lili
-21;male;Jim
+Name;Age;Gender
+Lili;22;female
+Jim;21;male