Golang从文本文件读取行到结构体切片的方法

Golang从文本文件读取行到结构体切片的方法 大家好,各位Gopher。

我正在尝试将包含名和姓的一些文本读入一个名为Name的结构体中,该结构体包含名和姓字段。

我有点卡住了。首先,为了让文本文件中的字符串分别被识别为firstNamelastName,我应该使用strings.split(" ")吗?如果我这样做,这基本上会将所有代码行变成多个切片,从而使处理Name的切片变得更加困难,而我不希望这样。以下是我目前的代码:

// Write a program which reads information from a file and represents it in a slice of structs.
// Assume that there is a text file which contains a series of names. Each line of the text file has
// a first name and a last name, in that order, separated by a single space on the line.
// Your program will define a name struct which has two fields, fname for the first name, and lname for
// the last name. Each field will be a string of size 20 (characters).
// Your program should prompt the user for the name of the text file. Your program will successively read
// each line of the text file and create a struct which contains the first and last names found in the file.
// Each struct created will be added to a slice, and after all lines have been read from the file,
// your program will have a slice containing one struct for each line in the file. After reading all
// lines from the file, your program should iterate through your slice of structs and print the first and
// last names found in each struct. Submit your source code for the program, “read.go”.

package main

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

//Name Struct
type Name struct {
	fname string
	lname string
}

func main() {
	inputReader := bufio.NewReader(os.Stdin)
	names := make([]Name, 0, 3)

	fmt.Println("Welcome! Please enter the name of the text file:")
	fileName, err := inputReader.ReadString('\n')
	if err != nil {
		log.Fatal(err)
	}

	fileName = strings.Trim(fileName, "\n")

	file, err := os.Open(fileName)
	if err != nil {
		log.Fatal(err)
	}

	defer file.Close()

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		s := strings.Split(scanner.Text(), " ")
		var aName Name
		aName.fname, aName.lname = s[0], s[1]
		names = append(names, aName)

	}

	for _, v := range names {
		fmt.Println(v)
	}

}

先谢谢了!


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

4 回复

我忘了提,我遇到了以下错误:"panic: runtime error: index out of range

goroutine 1"

我认为这与我使用 for scanner.Scan() 的 for 循环有关。谢谢!

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


scanner.Scan() 是用于前进到下一行的函数。你现在每个循环调用了它两次。

对于之前的 panic 错误,在尝试访问 Split() 返回的切片中的元素之前,请先检查其长度。

嗯,我没有使用 bufio 来读取文件名……而是使用了 fmt.Scan,并且没有使用 if !scanner.Scan,结果它就能正常工作了……

现在它能显示文件中的所有名字了。

package main
import "fmt"
import "os"
import "strings"
import "bufio"

type Name struct {
    fname string
    lname string
}

func main() {
    slice := make([]Name, 0, 3)
    fmt.Println("Enter file name (same directory):")

    var fileName string
    fmt.Scan(&fileName)

    file, e := os.Open(fileName)
    if e != nil {
        fmt.Println("Error is = ",e)
    }

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {

        s := strings.Split(scanner.Text(), " ")
        var namee Name
        namee.fname, namee.lname = s[0], s[1]
        slice = append(slice, namee)

    }

    file.Close()

    fmt.Println("\n********************\n")

    for _, v := range slice {
        fmt.Println(v.fname, v.lname)
    }
}

你的代码基本正确,但需要处理几个细节问题。以下是改进后的版本:

package main

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

type Name struct {
	fname string
	lname string
}

func main() {
	fmt.Print("Enter filename: ")
	var filename string
	fmt.Scanln(&filename)

	file, err := os.Open(filename)
	if err != nil {
		log.Fatal(err)
	}
	defer file.Close()

	var names []Name
	scanner := bufio.NewScanner(file)
	
	for scanner.Scan() {
		line := scanner.Text()
		parts := strings.Fields(line)
		
		if len(parts) >= 2 {
			// 确保字符串长度不超过20个字符
			fname := parts[0]
			lname := parts[1]
			
			if len(fname) > 20 {
				fname = fname[:20]
			}
			if len(lname) > 20 {
				lname = lname[:20]
			}
			
			names = append(names, Name{
				fname: fname,
				lname: lname,
			})
		}
	}

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

	for _, name := range names {
		fmt.Printf("First: %-20s Last: %-20s\n", name.fname, name.lname)
	}
}

关键改进点:

  1. 使用 strings.Fields() 替代 strings.Split(" "),它能更好地处理多个空格
  2. 添加了长度检查,确保每个字段不超过20个字符
  3. 改进了文件名输入方式,使用 fmt.Scanln() 更简洁
  4. 添加了错误检查 scanner.Err()
  5. 改进了输出格式,使显示更清晰

如果文件内容为:

John Doe
Jane Smith
Bob Johnson

输出将是:

First: John                 Last: Doe                  
First: Jane                 Last: Smith                
First: Bob                  Last: Johnson
回到顶部