Golang从文本文件读取数据到结构体的实现方法

Golang从文本文件读取数据到结构体的实现方法 我的结构体:

type GPSDataRow struct {
vehicletype   string
route         string
schedule      int
shift         int
busnumber     string
lowgrind      int
tripsstart    int
tripsend      int
directionid   int
directiontype string
directionname string
}

文件中的数据示例:Autobusai,65,02,1,2350,0,383,388,43576,D>C, 共有11个数据,全部用逗号分隔。 如何用文件中的数据填充我的结构体?文件大约有5000多行。

我尝试这样做:

for scanner.Scan() {
s := strings.Split(scanner.Text(), ",")
if !scanner.Scan() {
break
}
var gpsdataraw GPSDataRow
gpsdataraw.vehicletype, gpsdataraw.route, gpsdataraw.schedule, gpsdataraw.shift, gpsdataraw.busnumber, gpsdataraw.lowgrind, gpsdataraw.tripsstart, gpsdataraw.tripsend, gpsdataraw.directionid, gpsdataraw.directiontype, gpsdataraw.directionname = s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9], s[10]
var gpsdata = append(gpsdata, gpsdataraw)

}

但没有结果。


更多关于Golang从文本文件读取数据到结构体的实现方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

我认为如果你使用内置库 encoding/csv 来完成这个任务会更简单。

更多关于Golang从文本文件读取数据到结构体的实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


大家好,

感谢你们的回复,但在长时间研究这段代码后,我最终成功解析了所有数据并将其添加到结构体和映射中!

再次感谢你们的帮助,期待下次交流!

我过去在编程面试中使用过这个方法。将数据导入矩阵非常有效。

不过仍然面临为结构体生成唯一名称的挑战。

我提出的解决方案是将数据存储在数组中,数组长度与"文件"中的公交车数量相同。虽然不是最优方案,但这是一个开始。

https://play.golang.org/p/ASGnVUEPegD

@MantasSilanskas 欢迎加入社区!

你尝试过 io/utilreadFile 函数吗? https://golang.org/pkg/io/ioutil/#ReadFile 这会将数据添加到变量中

由于文件有多行,我建议先按 \n 分割。 然后你可以按 , 分割。

这样你会得到一个二维矩阵,可以通过循环将数据添加到你的结构体中。

不过,基于以上信息(没有多行文件的情况),以下是我将数据存入结构体的方案:

package main

import (
	"fmt"
	"log"
	"strconv"
	"strings"
)

type GPSDataRow struct {
	vehicleType   string
	route         string
	schedule      int
	shift         int
	busNumber     string
	lowGrind      int
	tripsStart    int
	tripsEnd      int
	directionID   int
	directionType string
	directionName string
}

func main() {
	var err error
	gps := new(GPSDataRow)

	data := "Autobusai,65,02,1,2350,0,383,388,43576,D>C"
	dataSlice := strings.Split(data, ",")

	for i, v := range dataSlice {
		switch i {
		case 0:
			gps.vehicleType = v
		case 1:
			gps.route = v
		case 2:
			gps.schedule, err = strconv.Atoi(v)
			if err != nil {
				log.Fatal(err)
			}
		case 3:
			gps.shift, err = strconv.Atoi(v)
			if err != nil {
				log.Fatal(err)
			}
		case 4:
			gps.busNumber = v
		case 5:
			gps.lowGrind, err = strconv.Atoi(v)
			if err != nil {
				log.Fatal(err)
			}
		case 6:
			gps.tripsStart, err = strconv.Atoi(v)
			if err != nil {
				log.Fatal(err)
			}
		case 7:
			gps.tripsEnd, err = strconv.Atoi(v)
			if err != nil {
				log.Fatal(err)
			}
		case 8:
			gps.directionID, err = strconv.Atoi(v)
			if err != nil {
				log.Fatal(err)
			}
		case 9:
			gps.directionType = v

		case 10:
			gps.directionName = v
		}
	}

	fmt.Println(gps.route)
	fmt.Println(gps.busNumber)
	fmt.Println(gps.directionType)
}

点击此处查看Go Playground版本。

附注:你需要找到为结构体创建多个实例的方法,否则在处理下一行数据时会覆盖前一个实例。

希望这对你有帮助。

你的代码有几个问题需要修正。主要问题是:

  1. 在循环中调用了两次 scanner.Scan(),这会导致跳过行
  2. 没有处理字符串到整数的转换
  3. 切片 gpsdata 需要先初始化

以下是修正后的代码:

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

type GPSDataRow struct {
    vehicletype   string
    route         string
    schedule      int
    shift         int
    busnumber     string
    lowgrind      int
    tripsstart    int
    tripsend      int
    directionid   int
    directiontype string
    directionname string
}

func main() {
    file, err := os.Open("yourfile.txt")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    var gpsdata []GPSDataRow
    scanner := bufio.NewScanner(file)

    for scanner.Scan() {
        line := scanner.Text()
        s := strings.Split(line, ",")
        
        // 确保有足够的字段
        if len(s) < 11 {
            continue
        }

        var gpsdataraw GPSDataRow
        gpsdataraw.vehicletype = s[0]
        gpsdataraw.route = s[1]
        
        // 转换字符串到整数
        gpsdataraw.schedule, _ = strconv.Atoi(s[2])
        gpsdataraw.shift, _ = strconv.Atoi(s[3])
        gpsdataraw.busnumber = s[4]
        gpsdataraw.lowgrind, _ = strconv.Atoi(s[5])
        gpsdataraw.tripsstart, _ = strconv.Atoi(s[6])
        gpsdataraw.tripsend, _ = strconv.Atoi(s[7])
        gpsdataraw.directionid, _ = strconv.Atoi(s[8])
        gpsdataraw.directiontype = s[9]
        gpsdataraw.directionname = s[10]

        gpsdata = append(gpsdata, gpsdataraw)
    }

    if err := scanner.Err(); err != nil {
        panic(err)
    }

    // 验证结果
    fmt.Printf("成功读取 %d 行数据\n", len(gpsdata))
    if len(gpsdata) > 0 {
        fmt.Printf("第一行数据: %+v\n", gpsdata[0])
    }
}

更健壮的版本,包含错误处理:

func parseGPSData(filePath string) ([]GPSDataRow, error) {
    file, err := os.Open(filePath)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    var gpsdata []GPSDataRow
    scanner := bufio.NewScanner(file)
    lineNumber := 0

    for scanner.Scan() {
        lineNumber++
        line := scanner.Text()
        s := strings.Split(line, ",")
        
        if len(s) < 11 {
            fmt.Printf("第 %d 行字段不足,跳过\n", lineNumber)
            continue
        }

        var row GPSDataRow
        row.vehicletype = s[0]
        row.route = s[1]
        
        // 带错误处理的转换
        if schedule, err := strconv.Atoi(s[2]); err == nil {
            row.schedule = schedule
        }
        
        if shift, err := strconv.Atoi(s[3]); err == nil {
            row.shift = shift
        }
        
        row.busnumber = s[4]
        
        if lowgrind, err := strconv.Atoi(s[5]); err == nil {
            row.lowgrind = lowgrind
        }
        
        if tripsstart, err := strconv.Atoi(s[6]); err == nil {
            row.tripsstart = tripsstart
        }
        
        if tripsend, err := strconv.Atoi(s[7]); err == nil {
            row.tripsend = tripsend
        }
        
        if directionid, err := strconv.Atoi(s[8]); err == nil {
            row.directionid = directionid
        }
        
        row.directiontype = s[9]
        row.directionname = s[10]

        gpsdata = append(gpsdata, row)
    }

    if err := scanner.Err(); err != nil {
        return nil, err
    }

    return gpsdata, nil
}

使用方法:

func main() {
    gpsdata, err := parseGPSData("data.txt")
    if err != nil {
        panic(err)
    }
    
    fmt.Printf("成功解析 %d 行GPS数据\n", len(gpsdata))
}

主要修正点:

  • 移除了多余的 scanner.Scan() 调用
  • 添加了字符串到整数的转换
  • 添加了错误处理和字段验证
  • 确保切片正确初始化
回到顶部