Go lang CSV read Error "wrong number of fields"

go言語CSVファイル読み取りエラー「wrong number of fields」

Problem

Original Code

package main

import "encoding/csv"

func readWord(path string) {
	file, err := os.Open(path)
	if err != nil {
		fmt.Println("Error: could not open file: ", path)
		return []string{}
	}
	defer file.Close()

	var words []string
	
	reader := csv.NewReader(file)
	records, err := reader.ReadAll() //read csv file
	if err != nil {
		fmt.Println("Error: failed to read CSV: ", err)
		return []string{}
	}
	for _, record := range records {
		for _, cell := range record {
			w := strings.TrimSpace(cell)
			if w != "" {
				words = append(words, w)
			}
		}
	}
	return words
}

CSV file

apple,banana,orange

grape,melon

strawberry

This error means one row has a different number of cells than the first row. By default, ReadAll() expects every row to have the same number of cells as the first row. So when rows have different numbers of cells, like the CSV above, it does not work.

Solution

package main

import "encoding/csv"

func readWord(path string) {
	file, err := os.Open(path)
	if err != nil {
		fmt.Println("Error: could not open file: ", path)
		return []string{}
	}
	defer file.Close()

	var words []string
	
	reader := csv.NewReader(file) //read csv file
	reader.FieldsPerRecord = -1
	records, err := reader.ReadAll()
	if err != nil {
		fmt.Println("Error: failed to read CSV: ", err)
		return []string{}
	}
	for _, record := range records {
		for _, cell := range record {
			w := strings.TrimSpace(cell)
			if w != "" {
				words = append(words, w)
			}
		}
	}
	return words
}

Insert reader.FieldsPerRecord = -1 between reader := csv.NewReader(file) and records, err := reader.ReadAll() (line 16). As mentioned earlier, by default it uses the first row’s cell count, but adding this option lets it read the file even when each row has a different number of cells.

問題

元のコード

package main

import "encoding/csv"

func readWord(path string) {
	file, err := os.Open(path)
	if err != nil {
		fmt.Println("Error: could not open file: ", path)
		return []string{}
	}
	defer file.Close()

	var words []string
	
	reader := csv.NewReader(file)
	records, err := reader.ReadAll() //読み取っている部分
	if err != nil {
		fmt.Println("Error: failed to read CSV: ", err)
		return []string{}
	}
	for _, record := range records {
		for _, cell := range record {
			w := strings.TrimSpace(cell)
			if w != "" {
				words = append(words, w)
			}
		}
	}
	return words
}

CSVファイル

apple,banana,orange

grape,melon

strawberry

このエラーは「二行目のセルが他と違う」というエラー。16行目のReadAll()は1行目のセル数を基準とするため、今回のように1行目と2行目のセル数が異なる場合正しく動作しない。

解決法

package main

import "encoding/csv"

func readWord(path string) {
	file, err := os.Open(path)
	if err != nil {
		fmt.Println("Error: could not open file: ", path)
		return []string{}
	}
	defer file.Close()

	var words []string
	
	reader := csv.NewReader(file) //読み取っている部分
	reader.FieldsPerRecord = -1
	records, err := reader.ReadAll()
	if err != nil {
		fmt.Println("Error: failed to read CSV: ", err)
		return []string{}
	}
	for _, record := range records {
		for _, cell := range record {
			w := strings.TrimSpace(cell)
			if w != "" {
				words = append(words, w)
			}
		}
	}
	return words
}

15行目reader := csv.NewReader(file)の後にreader.FieldsPerRecord = -1を入れる。
前述の通りデフォルトでは1行目のセル数を参照するが、このオプションを足すことでバラバラの行数でも読むことができる。

← Back to blog ← 記事一覧へ