Golang CSV文件解析与处理指南
Golang CSV文件解析与处理指南 我有一份以CSV格式导出的绩效报告,想将其导入到我的Web应用中。数据以如下格式呈现:
| 员工每日绩效 |
|---|
| 桥街 |
| Abbi Clarke |
| 日期 |
| 02/01/2019 |
| 03/01/2019 |
| 04/01/2019 |
| Adam Carter |
| 日期 |
| 02/01/2019 |
| 03/01/2019 |
| 04/01/2019 |
| James Sharpe |
| 日期 |
| 02/01/2019 |
| 03/01/2019 |
| 04/01/2019 |
我希望将每个团队成员的数据分离到一个映射切片 []map[string][]string 中,以团队成员姓名作为键,数字作为字符串切片——忽略所有其他内容。
这样我就可以使用 encoding/csv 包遍历每个映射,以便将其上传到我的数据库。
我应该如何以这种方式读取文档?
更多关于Golang CSV文件解析与处理指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
一些问题:
- 如何识别团队成员的姓名?
- 如何识别团队成员的“数据”?
- 根据你问题中的数据,预期的
[]map[string][]string结果应该是什么? - 你已经尝试过哪些方法?
- 它有效吗?
- 如果无效,具体哪里有问题?
更多关于Golang CSV文件解析与处理指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
- 每个团队成员对应一个人名。
- 后续的数据(以日期开头的行)是具体数值。
- 我希望将每个团队成员的数据子集存储到映射(map)中,并以团队成员的名字作为键。
- 我目前的解决方法是手动将数据分割成单独的CSV文件,每个文件对应一个团队成员的数据——我使用团队成员的名字作为文件名。然后,我使用encoding/csv包来读取每个文件。
我对Go语言(以及编程本身)还比较陌生——我已经在论坛上仔细搜索过,试图找到解决方案,但仍然没有成功!任何帮助都将不胜感激。
package main
import (
"encoding/csv"
"fmt"
"io"
"os"
"strings"
)
func parseCSV(filePath string) ([]map[string][]string, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()
reader := csv.NewReader(file)
var result []map[string][]string
var currentEmployee string
var employeeData []string
inDataSection := false
headerCount := 0
for {
record, err := reader.Read()
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
if len(record) == 0 {
continue
}
firstField := strings.TrimSpace(record[0])
if firstField == "员工每日绩效" || firstField == "桥街" {
continue
}
if strings.Contains(firstField, "/") {
if inDataSection && currentEmployee != "" {
employeeData = append(employeeData, strings.Join(record, ","))
}
continue
}
if isName(firstField) {
if currentEmployee != "" && len(employeeData) > 0 {
result = append(result, map[string][]string{
currentEmployee: employeeData,
})
}
currentEmployee = firstField
employeeData = []string{}
inDataSection = false
headerCount = 0
continue
}
if firstField == "日期" {
headerCount++
if headerCount == 2 {
inDataSection = true
}
continue
}
}
if currentEmployee != "" && len(employeeData) > 0 {
result = append(result, map[string][]string{
currentEmployee: employeeData,
})
}
return result, nil
}
func isName(field string) bool {
names := []string{"Abbi Clarke", "Adam Carter", "James Sharpe"}
for _, name := range names {
if field == name {
return true
}
}
return false
}
func main() {
data, err := parseCSV("performance.csv")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
for _, empMap := range data {
for name, records := range empMap {
fmt.Printf("Employee: %s\n", name)
for _, record := range records {
fmt.Printf(" Data: %s\n", record)
}
}
}
}
// 更健壮的版本,包含数据验证
package main
import (
"encoding/csv"
"fmt"
"io"
"os"
"strings"
)
type EmployeeData struct {
Name string
Records []string
}
func parseCSVAdvanced(filePath string) ([]map[string][]string, error) {
file, err := os.Open(filePath)
if err != nil {
return nil, err
}
defer file.Close()
reader := csv.NewReader(file)
reader.FieldsPerRecord = -1
var result []map[string][]string
var currentEmployee string
var recordsBuffer []string
dataMode := false
skipNext := false
for lineNum := 1; ; lineNum++ {
record, err := reader.Read()
if err == io.EOF {
break
}
if err != nil {
continue
}
if len(record) == 0 {
continue
}
firstCell := strings.TrimSpace(record[0])
switch {
case firstCell == "":
continue
case strings.Contains(firstCell, "员工每日绩效"):
continue
case strings.Contains(firstCell, "桥街"):
continue
case isEmployeeName(firstCell):
if currentEmployee != "" && len(recordsBuffer) > 0 {
result = append(result, map[string][]string{
currentEmployee: cleanRecords(recordsBuffer),
})
}
currentEmployee = firstCell
recordsBuffer = []string{}
dataMode = false
skipNext = false
case firstCell == "日期" && !skipNext:
skipNext = true
continue
case firstCell == "日期" && skipNext:
dataMode = true
skipNext = false
continue
case dataMode && isDate(firstCell):
recordsBuffer = append(recordsBuffer, strings.Join(record, ","))
default:
continue
}
}
if currentEmployee != "" && len(recordsBuffer) > 0 {
result = append(result, map[string][]string{
currentEmployee: cleanRecords(recordsBuffer),
})
}
return result, nil
}
func isEmployeeName(str string) bool {
knownNames := map[string]bool{
"Abbi Clarke": true,
"Adam Carter": true,
"James Sharpe": true,
}
return knownNames[str]
}
func isDate(str string) bool {
return strings.Contains(str, "/") && len(str) == 10
}
func cleanRecords(records []string) []string {
var cleaned []string
for _, r := range records {
trimmed := strings.TrimSpace(r)
if trimmed != "" {
cleaned = append(cleaned, trimmed)
}
}
return cleaned
}
func main() {
data, err := parseCSVAdvanced("performance.csv")
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
for i, empMap := range data {
fmt.Printf("Record %d:\n", i+1)
for name, records := range empMap {
fmt.Printf(" Employee: %s\n", name)
fmt.Printf(" Record count: %d\n", len(records))
for j, record := range records {
fmt.Printf(" [%d] %s\n", j+1, record)
}
}
}
}
// 数据库上传示例
package main
import (
"database/sql"
"encoding/csv"
"fmt"
"strings"
_ "github.com/lib/pq"
)
func uploadToDB(data []map[string][]string, db *sql.DB) error {
for _, empMap := range data {
for empName, records := range empMap {
for _, record := range records {
fields := strings.Split(record, ",")
if len(fields) >= 9 {
_, err := db.Exec(`
INSERT INTO performance
(employee_name, date, service_excl, service_total,
course_excl, course_total, product_excl, product_total,
hours, minutes)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,
empName,
fields[0],
fields[1],
fields[2],
fields[3],
fields[4],
fields[5],
fields[6],
fields[7],
fields[8],
)
if err != nil {
return err
}
}
}
}
}
return nil
}

