go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/pkg/funcs/read_csv.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package funcs
     9  
    10  import (
    11  	"context"
    12  	"encoding/csv"
    13  	"fmt"
    14  	"io"
    15  	"os"
    16  	"time"
    17  
    18  	"go.charczuk.com/projects/nodes/pkg/incrutil"
    19  	"go.charczuk.com/projects/nodes/pkg/types"
    20  )
    21  
    22  // ReadCSV reads a csv from a given file input and returns a table.
    23  //
    24  // The table values initially will be string.
    25  func ReadCSV(ctx context.Context, filepath string, modTime time.Time) (output *types.Table, err error) {
    26  	f, err := os.Open(os.ExpandEnv(filepath))
    27  	if err != nil {
    28  		return
    29  	}
    30  	defer f.Close()
    31  
    32  	output = new(types.Table)
    33  
    34  	csvr := csv.NewReader(f)
    35  	var record []string
    36  	for {
    37  		record, err = csvr.Read()
    38  		if err == io.EOF {
    39  			err = nil
    40  			break
    41  		}
    42  		if len(output.Columns) == 0 {
    43  			output.Columns = make([]types.TableColumn, len(record))
    44  			for index, value := range record {
    45  				output.Columns[index] = types.TableColumn{
    46  					ValueType: incrutil.ValueTypeString,
    47  					Name:      value,
    48  				}
    49  			}
    50  			continue
    51  		}
    52  		if len(record) > len(output.Columns) {
    53  			err = fmt.Errorf("invalid csv row; more columns present than the header row")
    54  			return
    55  		}
    56  		for index, value := range record {
    57  			output.Columns[index].Values = append(output.Columns[index].Values, value)
    58  		}
    59  	}
    60  	return
    61  }