中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

golang怎么操作csv文件

發布時間:2022-02-07 09:55:40 來源:億速云 閱讀:189 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“golang怎么操作csv文件”,內容詳細,步驟清晰,細節處理妥當,希望這篇“golang怎么操作csv文件”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

練習要求:

寫一個小程序解析data.csv,要求實現如下功能:

  1. 接收姓名作為參數。

  2. 根據姓名查找出對應員工的工時信息,并將 日期、上班、下班、工時 打印到標準輸出。

  3. 將上一條輸出的內容保存到json文件,使用姓名.json作為文件名

  4. 根據上條中生成的json文件,計算出該員工的月總工時、每周的平均工時。

考察點:

  1. 結構體定義

  2. 字符串拼接

  3. 類型轉換

  4. 編碼轉換

  5. 命令行參數解析

  6. 文件讀取

  7. json庫使用

編碼:

package main
 
import (
    "bufio"
    "encoding/json"
    "errors"
    "flag"
    "fmt"
    "io"
    "os"
    "strconv"
    "strings"
 
    "github.com/axgle/mahonia"
)
 
//給 fmt.Println 起一個短的別名。
var p = fmt.Println
 
//定義一個全局變量 一個月上班加休息總天數
var gAllDays float64 = 0
 
//定義一個全局變量 考勤異常的天數
var gAbnormalDays int = 0
 
//上班信息
type WorkInfo struct {
    WorkDate  string //上班日期
    StartTime string //上班打卡時間
    EndTime   string //下班打卡時間
    LaborHour string //當天工時
}
 
//考勤異常信息
type WorkAbnormalInfo struct {
    WorkDate   string //上班日期
    NormalInfo string //異常信息
}
 
/**
 * @brief  把當前字符串按照指定方式進行編碼
 * @param[in]       src                   待進行轉碼的字符串
 * @param[in]       srcCode               字符串當前編碼
 * @param[in]       tagCode               要轉換的編碼
 * @return   進行轉換后的字符串
 */
func ConvertToString(src string, srcCode string, tagCode string) (string, error) {
    if len(src) == 0 || len(srcCode) == 0 || len(tagCode) == 0 {
        return "", errors.New("input arguments error")
    }
    srcCoder := mahonia.NewDecoder(srcCode)
    srcResult := srcCoder.ConvertString(src)
    tagCoder := mahonia.NewDecoder(tagCode)
    _, cdata, _ := tagCoder.Translate([]byte(srcResult), true)
    result := string(cdata)
 
    return result, nil
}
 
/**
 * @brief            寫入數據到指定名字的文件中
 * @param[in]       buf                    待寫入的數據內容
 * @param[in]       name                文件名字
 * @return   成功返回nil 失敗返回error    錯誤信息
 */
func WriteFile(name string, buf string) error {
    if len(name) == 0 || len(buf) == 0 {
        return errors.New("input arguments error")
    }
 
    fout, err := os.OpenFile(name, os.O_CREATE|os.O_RDWR, 0666)
    defer fout.Close()
    if err != nil {
        return err
    }
 
    //寫入到本地文件中
    fout.WriteString(buf)
 
    return nil
}
 
/**
 * @brief  讀取文件
 * @param[in]       name            文件名(可以加路徑)
 * @return   成功返回 文件內容,失敗返回error    錯誤信息
 */
func ReadFile(name string) ([]byte, error) {
    if len(name) == 0 {
        return nil, errors.New("input arguments error")
    }
 
    //打開本地文件 讀取出全部數據
    fin, err := os.Open(name)
    defer fin.Close()
    if err != nil {
        return nil, errors.New("Close error")
    }
 
    buf_len, _ := fin.Seek(0, os.SEEK_END)
    fin.Seek(0, os.SEEK_SET)
 
    buf := make([]byte, buf_len)
    fin.Read(buf)
 
    return buf, nil
}
 
/**
 * @brief  讀取csv文件并打印指定員工信息
 * @param[in]       csvName            csv文件名(可以加路徑)
 * @param[in]       employeeName        員工名字
 * @return   成功返回 員工結構體信息,失敗返回error    錯誤信息
 */
func ReadCsvFile(csvName string, employeeName string) ([]WorkInfo, error) {
    if len(csvName) == 0 || len(employeeName) == 0 {
        return nil, errors.New("error: input arguments error")
    }
 
    var WorkInfoSet []WorkInfo
    var AbnormalSet []WorkAbnormalInfo
    var isExistName bool
    var dayCount float64 = 0
    var isNormal string
    var isNormalFlag bool
 
    var index int = 0
    var indexWorkDate int
    var indexStartTime int
    var indexEndTime int
    var indexLaborHour int
    var indexNormalInfo int
    var indexIsNormal int
 
    var i int = 0
 
    f, err := os.Open(csvName)
    if err != nil {
        return nil, err
    }
    defer f.Close()
 
    rd := bufio.NewReader(f)
    for {
        gbk_line, err := rd.ReadString('\n') //以'\n'為結束符讀入一行
        if err != nil || io.EOF == err {
            break
        }
        //p("gbk:", gbk_line)
 
        //把每一行gbk格式的字符串 轉換為 utf-8格式字符串
        utf8_line, _ := ConvertToString(gbk_line, "gbk", "utf-8")
 
        //對第一行進行處理
        if i == 0 {
            i = 1 //保證 只有第一行被處理
            p("utf8:", utf8_line)
            first_line := strings.Split(utf8_line, ",")
 
            for _, val := range first_line {
 
                if val == "日期" {
                    indexWorkDate = index
                }
                if val == "上班" {
                    indexStartTime = index
                }
                if val == "下班" {
                    indexEndTime = index
                }
                if val == "工時" {
                    indexLaborHour = index
                }
                if val == "是否有考勤異常" {
                    indexIsNormal = index
                }
                if val == "工時異常" {
                    indexNormalInfo = index
                }
 
                index++
            }
        }
 
        if strings.Contains(utf8_line, employeeName) {
            //把存在員工標記為true
            isExistName = true
 
            split_line := strings.Split(utf8_line, ",")
            person_temp := WorkInfo{split_line[indexWorkDate],
                split_line[indexStartTime],
                split_line[indexEndTime],
                split_line[indexLaborHour],
            }
 
            //考勤表天數加1
            dayCount++
            isNormal = split_line[indexIsNormal]
            //統計打卡異常的信息
            if isNormal == "是" {
                aInfo := WorkAbnormalInfo{split_line[indexWorkDate], split_line[indexNormalInfo]}
                AbnormalSet = append(AbnormalSet, aInfo)
 
                gAbnormalDays++
                isNormalFlag = true
            }
 
            WorkInfoSet = append(WorkInfoSet, person_temp)
        }
    }
 
    //統計考勤表里所有天數
    gAllDays = dayCount
    //對于不存在指定員工名字 的處理
    if !isExistName {
        p("\nRemind: There is no employee is csv file!\n")
        os.Exit(1)
    }
 
    //顯示員工所有考勤信息
    p("\n員工姓名:", employeeName)
    p("\n全部考勤信息:")
    for _, temp := range WorkInfoSet {
        fmt.Printf(
            "日期:%s ,上班:%s,下班:%s,工時:%s\n",
            temp.WorkDate,
            temp.StartTime,
            temp.EndTime,
            temp.LaborHour,
        )
    }
 
    //顯示員工打卡異常信息
    if isNormalFlag {
        p("\n異常考勤信息:")
        for _, val := range AbnormalSet {
            fmt.Printf("日期:%s , 異常信息:%s\n", val.WorkDate, val.NormalInfo)
        }
        p("溫馨提示:考勤出現異常信息,請及時給助理說明情況~_~\n")
    }
 
    return WorkInfoSet, nil
}
 
/**
* @brief  寫入json文件
* @param[in]       employeeName        員工名字
* @param[in]       workInfoSet            員工結構體信息
* @return   成功返回 nil,失敗返回error    錯誤信息
 */
func WriteJsonFile(employeeName string, workInfoSet []WorkInfo) error {
    if len(employeeName) == 0 || workInfoSet == nil {
        return errors.New("error: input arguments error")
    }
 
    //把輸出內容寫入name.json文件中
    filename := fmt.Sprintf("%s%s", employeeName, ".json")
    str, _ := json.Marshal(workInfoSet)
    err := WriteFile(string(str), filename)
    if err != nil {
        return err
    }
    return nil
}
 
/**
* @brief  讀取json文件
* @param[in]       employeeName        員工名字
* @return   成功返回 nil,失敗返回error    錯誤信息
 */
func ReadJsonFile(employeeName string) error {
    if len(employeeName) == 0 {
        return errors.New("error: input arguments error")
    }
 
    var WorkInfoSet []WorkInfo
    filename := fmt.Sprintf("%s%s", employeeName, ".json")
 
    ReadJsonBuf, err := ReadFile(filename)
    if err != nil {
        p(err.Error())
        return err
    }
    var sumHour float64 = 0.0
    var dayCount float64 = 0
    var weekCounts float64 = 0.0
    var averageWeekHour float64 = 0.0
 
    json.Unmarshal(ReadJsonBuf, &WorkInfoSet)
 
    for _, one_work := range WorkInfoSet {
 
        //去掉打卡異常情況和周六末情況 (如果周六末加班 數據依然計算進入總工時)
        if one_work.StartTime == "" || one_work.EndTime == "" {
            continue
        }
 
        one_day_hour, _ := strconv.ParseFloat(one_work.LaborHour, 64)
        sumHour += one_day_hour
        dayCount++
    }
 
    fmt.Printf("根據json文件計算工時,考勤正常天數:%2.0f, 異常天數:%d\n", dayCount, gAbnormalDays)
    weekCounts = gAllDays / 7
    averageWeekHour = sumHour / weekCounts
    //p("考勤表總天數:", gAllDays, ",共多少周:", week_counts)
 
    fmt.Printf("月總工時:%.4f 每周的平均工時:%.4f\n\n", sumHour, averageWeekHour)
 
    return nil
}
 
func main() {
    args := os.Args
 
    input := flag.String("i", "查無此人", "input employee name")
    path := flag.String("p", "./data.csv", "input csv file path")
 
    flag.Parse()
 
    if len(args) == 1 {
        fmt.Println("./main: missing operand")
        fmt.Println("Try `./main -h' or './main --help' for more information.")
        return
    }
 
    var csvName string = *path
    var employeeName string = *input
 
    //讀取csv文件并打印指定員工信息
    WorkInfoSet, err := ReadCsvFile(csvName, employeeName)
    if err != nil {
        p(err.Error())
        return
    }
 
    //把指定員工信息寫入json文件
    err = WriteJsonFile(employeeName, WorkInfoSet)
    if err != nil {
        p(err.Error())
        return
    }
 
    //讀取json文件并計算指定員工總工時和平均工時
    err = ReadJsonFile(employeeName)
    if err != nil {
        p(err.Error())
        return
    }
}

README.md

- USAGE: Analysis csv file command [arguments] ...

- The commands are:
-    -h , --help    cmd help.

- The commands are:
-    -i  input employee name.

- The commands are:
-    -p  input csv file path.

-當文件中不存在指定員工名字時,返回提醒信息


-參考鏈接:
- Golang GBK轉UTF-8 參考鏈接:https://blog.csdn.net/qq_33285730/article/details/73239263
- golang 文件按行讀取:https://studygolang.com/articles/282
- golang strings包方法:https://studygolang.com/articles/2881

附:使用Golang導出CSV數據并解決數據亂碼問題

在日常開發中,針對數據導出,我們可以導出Excel格式,但是如果是針對大數據量的導出,直接導出為Excel格式可能需要占用大量內存,且導出速度很慢。這個時候我們就需要導出為CSV格式。

CSV 格式

CSV本質上是文本文件,該文件有以下要求:

  • 列之間用逗號分隔,行之間用換行分隔

  • 單元格如果有逗號、引號之類的字符,該單元格需要使用雙引號括起來

  • 如果內容包含中文,直接輸出可能會亂碼

實現方式

golang 官方有csv的庫,可以很容易的實現csv數據的寫入。

golang實現csv數據寫文件

func main() {
	f, err := os.Create("data.csv")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	f.WriteString("\xEF\xBB\xBF") // 寫入UTF-8 BOM,避免使用Microsoft Excel打開亂碼

	writer := csv.NewWriter(f)
	writer.Write([]string{"編號", "姓名", "年齡"})
	writer.Write([]string{"1", "張三", "23"})
	writer.Write([]string{"2", "李四", "24"})
	writer.Write([]string{"3", "王五", "25"})
	writer.Write([]string{"4", "趙六", "26"})
	writer.Flush() // 此時才會將緩沖區數據寫入
}

golang實現web導出csv數據

此處以gin框架為例,如果用的go官方web庫,其實差不多是一樣的:

func ExportCsv(c *gin.Context) {
	bytesBuffer := &bytes.Buffer{}
	bytesBuffer.WriteString("\xEF\xBB\xBF") // 寫入UTF-8 BOM,避免使用Microsoft Excel打開亂碼

	writer := csv.NewWriter(bytesBuffer)
	writer.Write([]string{"編號", "姓名", "年齡"})
	writer.Write([]string{"1", "張三", "23"})
	writer.Write([]string{"2", "李四", "24"})
	writer.Write([]string{"3", "王五", "25"})
	writer.Write([]string{"4", "趙六", "26"})

	writer.Flush() // 此時才會將緩沖區數據寫入

	// 設置下載的文件名
	c.Writer.Header().Set("Content-Disposition", "attachment;filename=data.csv")
	// 設置文件類型以及輸出數據
	c.Data(http.StatusOK, "text/csv", bytesBuffer.Bytes())
	return
}

讀到這里,這篇“golang怎么操作csv文件”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

苍山县| 庄河市| 澄城县| 芒康县| 新野县| 石景山区| 武冈市| 花莲市| 晋江市| 常熟市| 七台河市| 武穴市| 濮阳县| 育儿| 东明县| 波密县| 象山县| 日土县| 屯留县| 萍乡市| 咸阳市| 浑源县| 汝阳县| 安仁县| 广安市| 湘西| 密云县| 辉南县| 丽水市| 福州市| 瑞昌市| 招远市| 穆棱市| 托克逊县| 合江县| 巴塘县| 汤原县| 盈江县| 九江市| 平果县| 洛南县|